Merge
authorduke
Wed, 05 Jul 2017 17:50:47 +0200
changeset 10448 5dd1f9701b1c
parent 10447 301b3b8fc6aa (current diff)
parent 10446 c19bcd1f9148 (diff)
child 10450 421134a8b841
Merge
--- a/.hgtags-top-repo	Thu Sep 15 18:53:21 2011 -0700
+++ b/.hgtags-top-repo	Wed Jul 05 17:50:47 2017 +0200
@@ -126,3 +126,4 @@
 69f592185747226a9c765a9fe139c1d34d616f9c jdk8-b02
 587bb549dff83131b65f40aa51864f69562f34a7 jdk8-b03
 0b66a233bfb9ba2ebda1e5cdfdb0373d6c1e3c69 jdk8-b04
+b910aac18c772b823b1f7da03e2c6528725cc6de jdk8-b05
--- a/corba/.hgtags	Thu Sep 15 18:53:21 2011 -0700
+++ b/corba/.hgtags	Wed Jul 05 17:50:47 2017 +0200
@@ -126,3 +126,4 @@
 ed8d94519a87b4adac270c3eec9134ff1f62bff5 jdk8-b02
 cd0da00694fbce642db9be936d3e4909a71d911d jdk8-b03
 60a68d688e24473cf84dedd1e60901a61ab82555 jdk8-b04
+cc1b599b986a37cb57de4584c5e58169766ca535 jdk8-b05
--- a/hotspot/.hgtags	Thu Sep 15 18:53:21 2011 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 17:50:47 2017 +0200
@@ -178,3 +178,4 @@
 31e253c1da429124bb87570ab095d9bc89850d0a jdk8-b02
 3a2fb61165dfc72e398179a2796d740c8da5b8c0 jdk8-b03
 0fa3ace511fe98fe948e751531f3e2b7c60c8376 jdk8-b04
+dce7d24674f4d0bed00de24f00119057fdce7cfb jdk8-b05
--- a/jdk/.hgtags	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/.hgtags	Wed Jul 05 17:50:47 2017 +0200
@@ -126,3 +126,4 @@
 13e70aa1398eb959c54bc68b783ca0eef1286ad2 jdk8-b02
 7989ee9fe673a87f4db3917fa6a005732a6a9b85 jdk8-b03
 fc569517f3cf242f90ce3503b743eb5553938946 jdk8-b04
+0b32369b83d81c226a2e79e730f3a8c0d2595e92 jdk8-b05
--- a/jdk/make/com/sun/servicetag/Makefile	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/make/com/sun/servicetag/Makefile	Wed Jul 05 17:50:47 2017 +0200
@@ -47,7 +47,7 @@
 # Add all properties files to the FILES_copy list
 SWORDFISH_properties := $(shell \
        $(CD) $(SHARE_SRC)/classes/com/sun/servicetag/resources; \
-       $(FIND) . -name 'javase_*_swordfish.properties' -print ; \
+       $(FIND) . -name 'javase_*.properties' -print ; \
     )
 FILES_copy += $(shell \
    for f in $(SWORDFISH_properties) ; do \
--- a/jdk/make/jprt.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/make/jprt.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -258,6 +258,15 @@
     windows_i586_5.1-product-c1-jdk_security3, 			\
     windows_x64_5.2-product-c2-jdk_security3, 			\
     								\
+    solaris_sparc_5.10-product-c1-jdk_sound, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_sound, 			\
+    solaris_i586_5.10-product-c1-jdk_sound, 			\
+    solaris_x64_5.10-product-c2-jdk_sound, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_sound, 			\
+    linux_x64_2.6-product-c2-jdk_sound, 			\
+    windows_i586_5.1-product-c1-jdk_sound, 			\
+    windows_x64_5.2-product-c2-jdk_sound, 			\
+    								\
     solaris_sparc_5.10-product-c1-jdk_swing, 			\
     solaris_sparcv9_5.10-product-c2-jdk_swing, 			\
     solaris_i586_5.10-product-c1-jdk_swing, 			\
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java	Wed Jul 05 17:50:47 2017 +0200
@@ -763,7 +763,7 @@
                 }
             } catch (IllegalThumbException e) {
                 // Should never happen
-                throw new InternalError("Illegal thumb in setThumbnail!");
+                throw new InternalError("Illegal thumb in setThumbnail!", e);
             }
         }
 
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java	Wed Jul 05 17:50:47 2017 +0200
@@ -529,21 +529,25 @@
         Locale l = fc.getLocale();
 
         enterFolderNameLabelText = UIManager.getString("FileChooser.enterFolderNameLabelText",l);
-        enterFolderNameLabelMnemonic = UIManager.getInt("FileChooser.enterFolderNameLabelMnemonic");
+        enterFolderNameLabelMnemonic = getMnemonic("FileChooser.enterFolderNameLabelMnemonic", l);
         enterFileNameLabelText = UIManager.getString("FileChooser.enterFileNameLabelText",l);
-        enterFileNameLabelMnemonic = UIManager.getInt("FileChooser.enterFileNameLabelMnemonic");
+        enterFileNameLabelMnemonic = getMnemonic("FileChooser.enterFileNameLabelMnemonic", l);
 
         filesLabelText = UIManager.getString("FileChooser.filesLabelText",l);
-        filesLabelMnemonic = UIManager.getInt("FileChooser.filesLabelMnemonic");
+        filesLabelMnemonic = getMnemonic("FileChooser.filesLabelMnemonic", l);
 
         foldersLabelText = UIManager.getString("FileChooser.foldersLabelText",l);
-        foldersLabelMnemonic = UIManager.getInt("FileChooser.foldersLabelMnemonic");
+        foldersLabelMnemonic = getMnemonic("FileChooser.foldersLabelMnemonic", l);
 
         pathLabelText = UIManager.getString("FileChooser.pathLabelText",l);
-        pathLabelMnemonic = UIManager.getInt("FileChooser.pathLabelMnemonic");
+        pathLabelMnemonic = getMnemonic("FileChooser.pathLabelMnemonic", l);
 
         filterLabelText = UIManager.getString("FileChooser.filterLabelText",l);
-        filterLabelMnemonic = UIManager.getInt("FileChooser.filterLabelMnemonic");
+        filterLabelMnemonic = getMnemonic("FileChooser.filterLabelMnemonic", l);
+    }
+
+    private Integer getMnemonic(String key, Locale l) {
+        return SwingUtilities2.getUIDefaultsInt(key, l);
     }
 
     protected void installIcons(JFileChooser fc) {
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1215,11 +1215,6 @@
             "EditorPane.focusInputMap", multilineInputMap,
 
 
-            "FileChooser.pathLabelMnemonic", new Integer(KeyEvent.VK_P), // 'p'
-            "FileChooser.filterLabelMnemonic", new Integer (KeyEvent.VK_R), // 'r'
-            "FileChooser.foldersLabelMnemonic", new Integer (KeyEvent.VK_L), // 'l'
-            "FileChooser.filesLabelMnemonic", new Integer (KeyEvent.VK_I), // 'i'
-            "FileChooser.enterFileNameLabelMnemonic", new Integer (KeyEvent.VK_N), // 'n'
             "FileChooser.ancestorInputMap",
                new UIDefaults.LazyInputMap(new Object[] {
                      "ESCAPE", "cancelSelection"
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -27,10 +27,15 @@
 FileChooser.updateButtonText=Update
 FileChooser.helpButtonText=Help
 FileChooser.pathLabelText=Enter path or folder name:
+FileChooser.pathLabelMnemonic=80
 FileChooser.filterLabelText=Filter
+FileChooser.filterLabelMnemonic=82
 FileChooser.foldersLabelText=Folders
+FileChooser.foldersLabelMnemonic=76
 FileChooser.filesLabelText=Files
+FileChooser.filesLabelMnemonic=73
 FileChooser.enterFileNameLabelText=Enter file name:
+FileChooser.enterFileNameLabelMnemonic=78
 FileChooser.enterFolderNameLabelText=Enter folder name:
 
 FileChooser.cancelButtonToolTipText=Abort file chooser dialog.
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_de.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_de.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -27,10 +27,15 @@
 FileChooser.updateButtonText=Aktualisieren
 FileChooser.helpButtonText=Hilfe
 FileChooser.pathLabelText=Pfad- oder Ordnernamen eingeben:
+FileChooser.pathLabelMnemonic=80
 FileChooser.filterLabelText=Filter
+FileChooser.filterLabelMnemonic=82
 FileChooser.foldersLabelText=Ordner
+FileChooser.foldersLabelMnemonic=76
 FileChooser.filesLabelText=Dateien
+FileChooser.filesLabelMnemonic=73
 FileChooser.enterFileNameLabelText=Dateinamen eingeben:
+FileChooser.enterFileNameLabelMnemonic=78
 FileChooser.enterFolderNameLabelText=Ordnernamen eingeben:
 
 FileChooser.cancelButtonToolTipText=Dialogfeld f\u00FCr Dateiauswahl schlie\u00DFen.
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_es.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_es.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -27,10 +27,15 @@
 FileChooser.updateButtonText=Actualizar
 FileChooser.helpButtonText=Ayuda
 FileChooser.pathLabelText=Introducir nombre de la ruta de acceso o carpeta:
+FileChooser.pathLabelMnemonic=80
 FileChooser.filterLabelText=Filtro
+FileChooser.filterLabelMnemonic=82
 FileChooser.foldersLabelText=Carpetas
+FileChooser.foldersLabelMnemonic=76
 FileChooser.filesLabelText=Archivos
+FileChooser.filesLabelMnemonic=73
 FileChooser.enterFileNameLabelText=Introducir nombre de archivo:
+FileChooser.enterFileNameLabelMnemonic=78
 FileChooser.enterFolderNameLabelText=Introducir nombre de carpeta:
 
 FileChooser.cancelButtonToolTipText=Abortar cuadro de di\u00E1logo del selector de archivos.
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_fr.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_fr.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -27,10 +27,15 @@
 FileChooser.updateButtonText=Mettre \u00E0 jour
 FileChooser.helpButtonText=Aide
 FileChooser.pathLabelText=Entrez le chemin ou le nom du dossier :
+FileChooser.pathLabelMnemonic=80
 FileChooser.filterLabelText=Filtre
+FileChooser.filterLabelMnemonic=82
 FileChooser.foldersLabelText=Dossiers
+FileChooser.foldersLabelMnemonic=76
 FileChooser.filesLabelText=Fichiers
+FileChooser.filesLabelMnemonic=73
 FileChooser.enterFileNameLabelText=Entrez le nom du fichier :
+FileChooser.enterFileNameLabelMnemonic=78
 FileChooser.enterFolderNameLabelText=Entrez le nom du dossier :
 
 FileChooser.cancelButtonToolTipText=Ferme la bo\u00EEte de dialogue du s\u00E9lecteur de fichiers.
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_it.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_it.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -27,10 +27,15 @@
 FileChooser.updateButtonText=Aggiorna
 FileChooser.helpButtonText=?
 FileChooser.pathLabelText=Percorso o nome cartella:
+FileChooser.pathLabelMnemonic=80
 FileChooser.filterLabelText=Filtro
+FileChooser.filterLabelMnemonic=82
 FileChooser.foldersLabelText=Cartelle
+FileChooser.foldersLabelMnemonic=76
 FileChooser.filesLabelText=File
+FileChooser.filesLabelMnemonic=73
 FileChooser.enterFileNameLabelText=Nome file:
+FileChooser.enterFileNameLabelMnemonic=78
 FileChooser.enterFolderNameLabelText=Nome cartella:
 
 FileChooser.cancelButtonToolTipText=Chiude la finestra di dialogo di selezione file.
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ja.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ja.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -27,10 +27,15 @@
 FileChooser.updateButtonText=\u66F4\u65B0
 FileChooser.helpButtonText=\u30D8\u30EB\u30D7
 FileChooser.pathLabelText=\u30D1\u30B9\u307E\u305F\u306F\u30D5\u30A9\u30EB\u30C0\u540D\u3092\u5165\u529B:
+FileChooser.pathLabelMnemonic=80
 FileChooser.filterLabelText=\u30D5\u30A3\u30EB\u30BF
+FileChooser.filterLabelMnemonic=82
 FileChooser.foldersLabelText=\u30D5\u30A9\u30EB\u30C0
+FileChooser.foldersLabelMnemonic=76
 FileChooser.filesLabelText=\u30D5\u30A1\u30A4\u30EB
+FileChooser.filesLabelMnemonic=73
 FileChooser.enterFileNameLabelText=\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u5165\u529B:
+FileChooser.enterFileNameLabelMnemonic=78
 FileChooser.enterFolderNameLabelText=\u30D5\u30A9\u30EB\u30C0\u540D\u3092\u5165\u529B:
 
 FileChooser.cancelButtonToolTipText=\u30D5\u30A1\u30A4\u30EB\u30FB\u30C1\u30E5\u30FC\u30B6\u30FB\u30C0\u30A4\u30A2\u30ED\u30B0\u3092\u7D42\u4E86\u3057\u307E\u3059\u3002
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ko.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ko.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -27,10 +27,15 @@
 FileChooser.updateButtonText=\uAC31\uC2E0
 FileChooser.helpButtonText=\uB3C4\uC6C0\uB9D0
 FileChooser.pathLabelText=\uACBD\uB85C \uB610\uB294 \uD3F4\uB354 \uC774\uB984 \uC785\uB825:
+FileChooser.pathLabelMnemonic=80
 FileChooser.filterLabelText=\uD544\uD130
+FileChooser.filterLabelMnemonic=82
 FileChooser.foldersLabelText=\uD3F4\uB354
+FileChooser.foldersLabelMnemonic=76
 FileChooser.filesLabelText=\uD30C\uC77C
+FileChooser.filesLabelMnemonic=73
 FileChooser.enterFileNameLabelText=\uD30C\uC77C \uC774\uB984 \uC785\uB825:
+FileChooser.enterFileNameLabelMnemonic=78
 FileChooser.enterFolderNameLabelText=\uD3F4\uB354 \uC774\uB984 \uC785\uB825:
 
 FileChooser.cancelButtonToolTipText=\uD30C\uC77C \uC120\uD0DD\uAE30 \uB300\uD654\uC0C1\uC790\uB97C \uC911\uB2E8\uD569\uB2C8\uB2E4.
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_pt_BR.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_pt_BR.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -27,10 +27,15 @@
 FileChooser.updateButtonText=Atualizar
 FileChooser.helpButtonText=Ajuda
 FileChooser.pathLabelText=Informar caminho ou nome da pasta:
+FileChooser.pathLabelMnemonic=80
 FileChooser.filterLabelText=Filtro
+FileChooser.filterLabelMnemonic=82
 FileChooser.foldersLabelText=Pastas
+FileChooser.foldersLabelMnemonic=76
 FileChooser.filesLabelText=Arquivos
+FileChooser.filesLabelMnemonic=73
 FileChooser.enterFileNameLabelText=Informar nome do arquivo:
+FileChooser.enterFileNameLabelMnemonic=78
 FileChooser.enterFolderNameLabelText=Informar nome da pasta:
 
 FileChooser.cancelButtonToolTipText=Abortar caixa de di\u00E1logo do seletor de arquivos.
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_sv.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_sv.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -27,10 +27,15 @@
 FileChooser.updateButtonText=Uppdatera
 FileChooser.helpButtonText=Hj\u00E4lp
 FileChooser.pathLabelText=Ange s\u00F6kv\u00E4g eller mappnamn:
+FileChooser.pathLabelMnemonic=80
 FileChooser.filterLabelText=Filter
+FileChooser.filterLabelMnemonic=82
 FileChooser.foldersLabelText=Mappar
+FileChooser.foldersLabelMnemonic=76
 FileChooser.filesLabelText=Filer
+FileChooser.filesLabelMnemonic=73
 FileChooser.enterFileNameLabelText=Ange filnamn:
+FileChooser.enterFileNameLabelMnemonic=78
 FileChooser.enterFolderNameLabelText=Ange ett mappnamn:
 
 FileChooser.cancelButtonToolTipText=Avbryt dialogrutan Filv\u00E4ljare.
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_zh_CN.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_zh_CN.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -27,10 +27,15 @@
 FileChooser.updateButtonText=\u66F4\u65B0
 FileChooser.helpButtonText=\u5E2E\u52A9
 FileChooser.pathLabelText=\u952E\u5165\u8DEF\u5F84\u6216\u6587\u4EF6\u5939\u540D: 
+FileChooser.pathLabelMnemonic=80
 FileChooser.filterLabelText=\u7B5B\u9009\u5668
+FileChooser.filterLabelMnemonic=82
 FileChooser.foldersLabelText=\u6587\u4EF6\u5939
+FileChooser.foldersLabelMnemonic=76
 FileChooser.filesLabelText=\u6587\u4EF6
+FileChooser.filesLabelMnemonic=73
 FileChooser.enterFileNameLabelText=\u952E\u5165\u6587\u4EF6\u540D: 
+FileChooser.enterFileNameLabelMnemonic=78
 FileChooser.enterFolderNameLabelText=\u8F93\u5165\u6587\u4EF6\u5939\u540D:
 
 FileChooser.cancelButtonToolTipText=\u4E2D\u6B62\u6587\u4EF6\u9009\u62E9\u5668\u5BF9\u8BDD\u6846\u3002
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_zh_TW.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_zh_TW.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -27,10 +27,15 @@
 FileChooser.updateButtonText=\u66F4\u65B0
 FileChooser.helpButtonText=\u8AAA\u660E
 FileChooser.pathLabelText=\u8F38\u5165\u8DEF\u5F91\u6216\u8CC7\u6599\u593E\u540D\u7A31:
+FileChooser.pathLabelMnemonic=80
 FileChooser.filterLabelText=\u7BE9\u9078
+FileChooser.filterLabelMnemonic=82
 FileChooser.foldersLabelText=\u8CC7\u6599\u593E
+FileChooser.foldersLabelMnemonic=76
 FileChooser.filesLabelText=\u6A94\u6848
+FileChooser.filesLabelMnemonic=73
 FileChooser.enterFileNameLabelText=\u8F38\u5165\u6A94\u6848\u540D\u7A31:
+FileChooser.enterFileNameLabelMnemonic=78
 FileChooser.enterFolderNameLabelText=\u8F38\u5165\u8CC7\u6599\u593E\u540D\u7A31:
 
 FileChooser.cancelButtonToolTipText=\u4E2D\u6B62\u6A94\u6848\u9078\u64C7\u5668\u5C0D\u8A71\u65B9\u584A\u3002
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java	Wed Jul 05 17:50:47 2017 +0200
@@ -528,16 +528,16 @@
 
         Locale l = fc.getLocale();
 
-        lookInLabelMnemonic = UIManager.getInt("FileChooser.lookInLabelMnemonic");
+        lookInLabelMnemonic = getMnemonic("FileChooser.lookInLabelMnemonic", l);
         lookInLabelText = UIManager.getString("FileChooser.lookInLabelText",l);
         saveInLabelText = UIManager.getString("FileChooser.saveInLabelText",l);
 
-        fileNameLabelMnemonic = UIManager.getInt("FileChooser.fileNameLabelMnemonic");
+        fileNameLabelMnemonic = getMnemonic("FileChooser.fileNameLabelMnemonic", l);
         fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText",l);
-        folderNameLabelMnemonic = UIManager.getInt("FileChooser.folderNameLabelMnemonic");
+        folderNameLabelMnemonic = getMnemonic("FileChooser.folderNameLabelMnemonic", l);
         folderNameLabelText = UIManager.getString("FileChooser.folderNameLabelText",l);
 
-        filesOfTypeLabelMnemonic = UIManager.getInt("FileChooser.filesOfTypeLabelMnemonic");
+        filesOfTypeLabelMnemonic = getMnemonic("FileChooser.filesOfTypeLabelMnemonic", l);
         filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText",l);
 
         upFolderToolTipText =  UIManager.getString("FileChooser.upFolderToolTipText",l);
@@ -550,6 +550,10 @@
         viewMenuButtonAccessibleName = UIManager.getString("FileChooser.viewMenuButtonAccessibleName",l);
     }
 
+    private Integer getMnemonic(String key, Locale l) {
+        return SwingUtilities2.getUIDefaultsInt(key, l);
+    }
+
     protected void installListeners(JFileChooser fc) {
         super.installListeners(fc);
         ActionMap actionMap = getActionMap();
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java	Wed Jul 05 17:50:47 2017 +0200
@@ -770,9 +770,6 @@
                                                                "icons/NewFolder.gif"),
             "FileChooser.useSystemExtensionHiding", Boolean.TRUE,
 
-            "FileChooser.lookInLabelMnemonic", Integer.valueOf(KeyEvent.VK_I),
-            "FileChooser.fileNameLabelMnemonic", Integer.valueOf(KeyEvent.VK_N),
-            "FileChooser.filesOfTypeLabelMnemonic", Integer.valueOf(KeyEvent.VK_T),
             "FileChooser.usesSingleFilePane", Boolean.TRUE,
             "FileChooser.noPlacesBar", new DesktopProperty("win.comdlg.noPlacesBar",
                                                            Boolean.FALSE),
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Look in:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Save in:
 FileChooser.fileNameLabelText=File name:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Folder name:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Files of type:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Up One Level
 FileChooser.upFolderAccessibleName=Up
 FileChooser.homeFolderToolTipText=Home
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_de.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_de.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Suchen in:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Speichern in:
 FileChooser.fileNameLabelText=Dateiname:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Ordnername:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Dateityp:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Eine Ebene h\u00F6her
 FileChooser.upFolderAccessibleName=Nach oben
 FileChooser.homeFolderToolTipText=Home
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_es.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_es.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Buscar en:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Guardar en:
 FileChooser.fileNameLabelText=Nombre de Archivo:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Nombre de la Carpeta:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Archivos de Tipo:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Subir un Nivel
 FileChooser.upFolderAccessibleName=Arriba
 FileChooser.homeFolderToolTipText=Inicio
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_fr.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_fr.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Rechercher dans :
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Enregistrer dans :
 FileChooser.fileNameLabelText=Nom du fichier :
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Nom du dossier :
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Fichiers de type :
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Remonte d'un niveau.
 FileChooser.upFolderAccessibleName=Monter
 FileChooser.homeFolderToolTipText=R\u00E9pertoire d'origine
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_it.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_it.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Cerca in:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Salva in:
 FileChooser.fileNameLabelText=Nome file:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Nome della cartella:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Tipo file:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Cartella superiore
 FileChooser.upFolderAccessibleName=Superiore
 FileChooser.homeFolderToolTipText=Home
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_ja.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_ja.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=\u53C2\u7167:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=\u4FDD\u5B58:
 FileChooser.fileNameLabelText=\u30D5\u30A1\u30A4\u30EB\u540D:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=\u30D5\u30A9\u30EB\u30C0\u540D:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=\u30D5\u30A1\u30A4\u30EB\u306E\u30BF\u30A4\u30D7:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=1\u30EC\u30D9\u30EB\u4E0A\u3078
 FileChooser.upFolderAccessibleName=\u4E0A\u3078
 FileChooser.homeFolderToolTipText=\u30DB\u30FC\u30E0
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_ko.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_ko.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=\uAC80\uC0C9 \uC704\uCE58:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=\uC800\uC7A5 \uC704\uCE58:
 FileChooser.fileNameLabelText=\uD30C\uC77C \uC774\uB984:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=\uD3F4\uB354 \uC774\uB984:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=\uD30C\uC77C \uC720\uD615:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=\uD55C \uB808\uBCA8 \uC704\uB85C
 FileChooser.upFolderAccessibleName=\uC704\uB85C
 FileChooser.homeFolderToolTipText=\uD648
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_pt_BR.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_pt_BR.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Consultar em:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Salvar em:
 FileChooser.fileNameLabelText=Nome do arquivo:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Nome da pasta:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Arquivos do tipo:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Um N\u00EDvel Acima
 FileChooser.upFolderAccessibleName=Acima
 FileChooser.homeFolderToolTipText=In\u00EDcio
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_sv.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_sv.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Leta i:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Spara i:
 FileChooser.fileNameLabelText=Filnamn:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Mapp:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Filformat:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Upp en niv\u00E5
 FileChooser.upFolderAccessibleName=Upp
 FileChooser.homeFolderToolTipText=Hem
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_zh_CN.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_zh_CN.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=\u67E5\u770B: 
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=\u4FDD\u5B58: 
 FileChooser.fileNameLabelText=\u6587\u4EF6\u540D: 
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=\u6587\u4EF6\u5939\u540D: 
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=\u6587\u4EF6\u7C7B\u578B: 
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=\u5411\u4E0A\u4E00\u7EA7
 FileChooser.upFolderAccessibleName=\u5411\u4E0A
 FileChooser.homeFolderToolTipText=\u4E3B\u76EE\u5F55
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_zh_TW.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_zh_TW.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=\u67E5\u8A62:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=\u5132\u5B58\u65BC: 
 FileChooser.fileNameLabelText=\u6A94\u6848\u540D\u7A31:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=\u8CC7\u6599\u593E\u540D\u7A31:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=\u6A94\u6848\u985E\u578B:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=\u5F80\u4E0A\u4E00\u5C64
 FileChooser.upFolderAccessibleName=\u5F80\u4E0A
 FileChooser.homeFolderToolTipText=\u4E3B\u76EE\u9304
--- a/jdk/src/share/classes/com/sun/jmx/snmp/SnmpCounter64.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/SnmpCounter64.java	Wed Jul 05 17:50:47 2017 +0200
@@ -186,7 +186,7 @@
             newclone = (SnmpCounter64) super.clone() ;
             newclone.value = value ;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError() ; // vm bug.
+            throw new InternalError(e) ; // vm bug.
         }
         return newclone ;
     }
--- a/jdk/src/share/classes/com/sun/jmx/snmp/SnmpInt.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/SnmpInt.java	Wed Jul 05 17:50:47 2017 +0200
@@ -232,7 +232,7 @@
             newclone = (SnmpInt) super.clone() ;
             newclone.value = value ;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError() ; // vm bug.
+            throw new InternalError(e) ; // vm bug.
         }
         return newclone ;
     }
--- a/jdk/src/share/classes/com/sun/jmx/snmp/SnmpNull.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/SnmpNull.java	Wed Jul 05 17:50:47 2017 +0200
@@ -129,7 +129,7 @@
             newclone = (SnmpNull) super.clone() ;
             newclone.tag = tag ;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError() ; // vm bug.
+            throw new InternalError(e) ; // vm bug.
         }
         return newclone ;
     }
--- a/jdk/src/share/classes/com/sun/jmx/snmp/SnmpString.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/SnmpString.java	Wed Jul 05 17:50:47 2017 +0200
@@ -250,7 +250,7 @@
             newclone.value = new byte[value.length] ;
             System.arraycopy(value, 0, newclone.value, 0, value.length) ;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError() ; // vm bug.
+            throw new InternalError(e) ; // vm bug.
         }
         return newclone ;
     }
--- a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpRequestHandler.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpRequestHandler.java	Wed Jul 05 17:50:47 2017 +0200
@@ -921,7 +921,7 @@
                 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                    "newTooBigMessage", "Internal error", x);
             }
-            throw new InternalError() ;
+            throw new InternalError(x) ;
         }
 
         return result ;
--- a/jdk/src/share/classes/com/sun/security/auth/module/NTSystem.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/security/auth/module/NTSystem.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, 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
@@ -33,6 +33,7 @@
 public class NTSystem {
 
     private native void getCurrent(boolean debug);
+    private native long getImpersonationToken0();
 
     private String userName;
     private String domain;
@@ -132,10 +133,14 @@
      *
      * @return an impersonation token for the current NT user.
      */
-    public long getImpersonationToken() {
+    public synchronized long getImpersonationToken() {
+        if (impersonationToken == 0) {
+            impersonationToken = getImpersonationToken0();
+        }
         return impersonationToken;
     }
 
+
     private void loadNative() {
         System.loadLibrary("jaas_nt");
     }
--- a/jdk/src/share/classes/com/sun/servicetag/BrowserSupport.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/servicetag/BrowserSupport.java	Wed Jul 05 17:50:47 2017 +0200
@@ -77,9 +77,7 @@
                         result = (Boolean) isDesktopSupportedMethod.invoke(null);
                     } catch (IllegalAccessException e) {
                         // should never reach here
-                        InternalError x =
-                            new InternalError("Desktop.getDesktop() method not found");
-                        x.initCause(e);
+                        throw new InternalError("Desktop.getDesktop() method not found", e);
                     } catch (InvocationTargetException e) {
                         // browser not supported
                         if (Util.isVerbose()) {
@@ -101,28 +99,10 @@
                 result = (Boolean) isSupportedMethod.invoke(desktopObj, browseField.get(null));
                 supported = result.booleanValue();
             }
-        } catch (ClassNotFoundException e) {
-            // browser not supported
-            if (Util.isVerbose()) {
-                e.printStackTrace();
-            }
-        } catch (NoSuchMethodException e) {
-            // browser not supported
-            if (Util.isVerbose()) {
-                e.printStackTrace();
-            }
-        } catch (NoSuchFieldException e) {
-            // browser not supported
-            if (Util.isVerbose()) {
-                e.printStackTrace();
-            }
         } catch (IllegalAccessException e) {
             // should never reach here
-            InternalError x =
-                    new InternalError("Desktop.getDesktop() method not found");
-            x.initCause(e);
-            throw x;
-        } catch (InvocationTargetException e) {
+            throw new InternalError("Desktop.getDesktop() method not found", e);
+        } catch (ReflectiveOperationException e) {
             // browser not supported
             if (Util.isVerbose()) {
                 e.printStackTrace();
@@ -175,10 +155,7 @@
             browseMethod.invoke(desktop, uri);
         } catch (IllegalAccessException e) {
             // should never reach here
-            InternalError x =
-                new InternalError("Desktop.getDesktop() method not found");
-            x.initCause(e);
-                throw x;
+            throw new InternalError("Desktop.getDesktop() method not found", e);
         } catch (InvocationTargetException e) {
             Throwable x = e.getCause();
             if (x != null) {
--- a/jdk/src/share/classes/com/sun/servicetag/Installer.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/servicetag/Installer.java	Wed Jul 05 17:50:47 2017 +0200
@@ -61,8 +61,8 @@
     private static RegistrationData registration;
     private static boolean supportRegistration;
     private static String registerHtmlParent;
-    private static Set<Locale> supportedLocales = new HashSet<Locale>();
-    private static Properties swordfishProps = null;
+    private static Set<Locale> supportedLocales = new HashSet<>();
+    private static Properties svcTagProps = null;
     private static String[] jreArchs = null;
     static {
         String dir = System.getProperty(SVCTAG_DIR_PATH);
@@ -94,7 +94,7 @@
         boolean cleanup = false;
         try {
             // Check if we have the swordfish entries for this JRE version
-            if (loadSwordfishEntries() == null) {
+            if (loadServiceTagProps() == null) {
                 return null;
             }
 
@@ -144,18 +144,14 @@
             return registration;
         }
         if (regXmlFile.exists()) {
-            BufferedInputStream in = null;
-            try {
-                in = new BufferedInputStream(new FileInputStream(regXmlFile));
+            try (BufferedInputStream in =
+                    new BufferedInputStream(new FileInputStream(regXmlFile)))
+            {
                 registration = RegistrationData.loadFromXML(in);
             } catch (IllegalArgumentException ex) {
                 System.err.println("Error: Bad registration data \"" +
                                     regXmlFile + "\":" + ex.getMessage());
                 throw ex;
-            } finally {
-                if (in != null) {
-                    in.close();
-                }
             }
         } else {
             registration = new RegistrationData();
@@ -186,18 +182,14 @@
         deleteRegistrationHtmlPage();
         getRegistrationHtmlPage();
 
-        BufferedOutputStream out = null;
-        try {
-            out = new BufferedOutputStream(new FileOutputStream(regXmlFile));
+        try (BufferedOutputStream out =
+                new BufferedOutputStream(new FileOutputStream(regXmlFile)))
+        {
             getRegistrationData().storeToXML(out);
         } catch (IllegalArgumentException ex) {
             System.err.println("Error: Bad registration data \"" +
                                 regXmlFile + "\":" + ex.getMessage());
             throw ex;
-        } finally {
-            if (out != null) {
-                out.close();
-            }
         }
     }
 
@@ -206,11 +198,9 @@
      * or empty set if file not exists.
      */
     private static Set<String> getInstalledURNs() throws IOException {
-        Set<String> urnSet = new HashSet<String>();
+        Set<String> urnSet = new HashSet<>();
         if (serviceTagFile.exists()) {
-            BufferedReader in = null;
-            try {
-                in = new BufferedReader(new FileReader(serviceTagFile));
+            try (BufferedReader in = new BufferedReader(new FileReader(serviceTagFile))) {
                 String urn;
                 while ((urn = in.readLine()) != null) {
                     urn = urn.trim();
@@ -218,10 +208,6 @@
                         urnSet.add(urn);
                     }
                 }
-            } finally {
-                if (in != null) {
-                    in.close();
-                }
             }
         }
         return urnSet;
@@ -237,9 +223,9 @@
     private static ServiceTag[] getJavaServiceTagArray() throws IOException {
         RegistrationData regData = getRegistrationData();
         Set<ServiceTag> svcTags = regData.getServiceTags();
-        Set<ServiceTag> result = new HashSet<ServiceTag>();
+        Set<ServiceTag> result = new HashSet<>();
 
-        Properties props = loadSwordfishEntries();
+        Properties props = loadServiceTagProps();
         String jdkUrn = props.getProperty("servicetag.jdk.urn");
         String jreUrn = props.getProperty("servicetag.jre.urn");
         for (ServiceTag st : svcTags) {
@@ -343,8 +329,7 @@
     }
 
     private static ServiceTag newServiceTag(String svcTagSource) throws IOException {
-        // Load the swoRDFish information for the service tag creation
-        Properties props = loadSwordfishEntries();
+        Properties props = loadServiceTagProps();
 
         // Determine the product URN and name
         String productURN;
@@ -442,52 +427,35 @@
             return;
         }
 
-        PrintWriter out = null;
-        try {
-            out = new PrintWriter(serviceTagFile);
-
+        try (PrintWriter out = new PrintWriter(serviceTagFile)) {
             ServiceTag[] javaSvcTags = getJavaServiceTagArray();
             for (ServiceTag st : javaSvcTags) {
                 // Write the instance_run to the servicetag file
                 String instanceURN = st.getInstanceURN();
                 out.println(instanceURN);
             }
-        } finally {
-            if (out != null) {
-                out.close();
-            }
         }
     }
 
     /**
-     * Load the values associated with the swoRDFish metadata entries
-     * for Java SE. The swoRDFish metadata entries are different for
-     * different release.
+     * Load the properties for generating Java SE service tags.
      *
      * @param version Version of Java SE
      */
-    private static synchronized Properties loadSwordfishEntries() throws IOException {
-        if (swordfishProps != null) {
-            return swordfishProps;
+    private static synchronized Properties loadServiceTagProps() throws IOException {
+        if (svcTagProps != null) {
+            return svcTagProps;
         }
 
-        // The version string for Java SE 6 is 1.6.0
-        // We just need the minor number in the version string
-        int version = Util.getJdkVersion();
-
-        String filename = "/com/sun/servicetag/resources/javase_" +
-                version + "_swordfish.properties";
-        InputStream in = Installer.class.getResourceAsStream(filename);
-        if (in == null) {
-            return null;
+        // For Java SE 8 and later releases, JDK and JRE both use
+        // the same product number.  The sworRDFish metadata were
+        // for legacy Sun part number.
+        String filename = "/com/sun/servicetag/resources/javase_servicetag.properties";
+        try (InputStream in = Installer.class.getResourceAsStream(filename)) {
+            svcTagProps = new Properties();
+            svcTagProps.load(in);
         }
-        swordfishProps = new Properties();
-        try {
-            swordfishProps.load(in);
-        } finally {
-            in.close();
-        }
-        return swordfishProps;
+        return svcTagProps;
     }
 
     /**
@@ -546,7 +514,7 @@
             return jreArchs;
         }
 
-        Set<String> archs = new HashSet<String>();
+        Set<String> archs = new HashSet<>();
 
         String os = System.getProperty("os.name");
         if (os.equals("SunOS") || os.equals("Linux")) {
@@ -681,16 +649,16 @@
         String country = locale.getCountry();
         String variant = locale.getVariant();
 
-        List<Locale> locales = new ArrayList<Locale>(3);
+        List<Locale> locales = new ArrayList<>(3);
         if (variant.length() > 0) {
             locales.add(locale);
         }
         if (country.length() > 0) {
-            locales.add((locales.size() == 0) ?
+            locales.add((locales.isEmpty()) ?
                         locale : new Locale(language, country, ""));
         }
         if (language.length() > 0) {
-            locales.add((locales.size() == 0) ?
+            locales.add((locales.isEmpty()) ?
                         locale : new Locale(language, "", ""));
         }
         return locales;
@@ -788,14 +756,11 @@
         // Format the registration data in one single line
         StringBuilder payload = new StringBuilder();
         String xml = regData.toString().replaceAll("\"", "%22");
-        BufferedReader reader = new BufferedReader(new StringReader(xml));
-        try {
+        try (BufferedReader reader = new BufferedReader(new StringReader(xml))) {
             String line = null;
             while ((line = reader.readLine()) != null) {
                 payload.append(line.trim());
             }
-        } finally {
-            reader.close();
         }
 
         String resourceFilename = "/com/sun/servicetag/resources/register";
--- a/jdk/src/share/classes/com/sun/servicetag/RegistrationDocument.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/servicetag/RegistrationDocument.java	Wed Jul 05 17:50:47 2017 +0200
@@ -150,9 +150,7 @@
         } catch (ParserConfigurationException pce) {
             // Parser with specific options can't be built
             // should not reach here
-            InternalError x = new InternalError("Error in creating the new document");
-            x.initCause(pce);
-            throw x;
+            throw new InternalError("Error in creating the new document", pce);
         }
     }
 
@@ -172,9 +170,7 @@
         } catch (ParserConfigurationException pce) {
             // Parser with specified options can't be built
             // should not reach here
-            InternalError x = new InternalError("Error in creating the new document");
-            x.initCause(pce);
-            throw x;
+            throw new InternalError("Error in creating the new document", pce);
         }
     }
 
@@ -195,20 +191,14 @@
                 new StreamResult(new BufferedWriter(new OutputStreamWriter(os, "UTF-8"))));
         } catch (UnsupportedEncodingException ue) {
             // Should not reach here
-            InternalError x = new InternalError("Error generated during transformation");
-            x.initCause(ue);
-            throw x;
+            throw new InternalError("Error generated during transformation", ue);
         } catch (TransformerConfigurationException tce) {
             // Error generated by the parser
             // Should not reach here
-            InternalError x = new InternalError("Error in creating the new document");
-            x.initCause(tce);
-            throw x;
+            throw new InternalError("Error in creating the new document", tce);
         } catch (TransformerException te) {
             // Error generated by the transformer
-            InternalError x = new InternalError("Error generated during transformation");
-            x.initCause(te);
-            throw x;
+            throw new InternalError("Error generated during transformation", te);
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/servicetag/resources/javase_servicetag.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -0,0 +1,29 @@
+# Copyright (c) 2011, 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.
+
+servicetag.jdk.urn     = Q8549
+servicetag.jdk.name    = Java Development Kit
+servicetag.jre.urn     = Q8549
+servicetag.jre.name    = Java Runtime Environment
+servicetag.parent.urn  = Q8549
+servicetag.parent.name = Java Platform, Standard Edition
--- a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Look In:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Save In:
 FileChooser.fileNameLabelText=File Name:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Folder name:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Files of Type:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Up One Level
 FileChooser.upFolderAccessibleName=Up
 FileChooser.homeFolderToolTipText=Home
--- a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_de.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_de.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Suchen in:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Speichern in:
 FileChooser.fileNameLabelText=Dateiname:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Ordnername:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Dateityp:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Eine Ebene h\u00F6her
 FileChooser.upFolderAccessibleName=Nach oben
 FileChooser.homeFolderToolTipText=Home
--- a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_es.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_es.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Buscar en:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Guardar en:
 FileChooser.fileNameLabelText=Nombre de Archivo:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Nombre de la Carpeta:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Archivos de Tipo:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Subir un Nivel
 FileChooser.upFolderAccessibleName=Arriba
 FileChooser.homeFolderToolTipText=Inicio
--- a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_fr.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_fr.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Rechercher dans :
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Enregistrer dans :
 FileChooser.fileNameLabelText=Nom du fichier :
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Nom du dossier :
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Fichiers de type :
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Remonte d'un niveau.
 FileChooser.upFolderAccessibleName=Monter
 FileChooser.homeFolderToolTipText=R\u00E9pertoire d'origine
--- a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_it.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_it.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Cerca in:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Salva in:
 FileChooser.fileNameLabelText=Nome file:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Nome della cartella:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Tipo file:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Cartella superiore
 FileChooser.upFolderAccessibleName=Superiore
 FileChooser.homeFolderToolTipText=Home
--- a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ja.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ja.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=\u53C2\u7167:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=\u4FDD\u5B58:
 FileChooser.fileNameLabelText=\u30D5\u30A1\u30A4\u30EB\u540D:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=\u30D5\u30A9\u30EB\u30C0\u540D:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=\u30D5\u30A1\u30A4\u30EB\u306E\u30BF\u30A4\u30D7:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=1\u30EC\u30D9\u30EB\u4E0A\u3078
 FileChooser.upFolderAccessibleName=\u4E0A\u3078
 FileChooser.homeFolderToolTipText=\u30DB\u30FC\u30E0
--- a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ko.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ko.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=\uAC80\uC0C9 \uC704\uCE58:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=\uC800\uC7A5 \uC704\uCE58:
 FileChooser.fileNameLabelText=\uD30C\uC77C \uC774\uB984:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=\uD3F4\uB354 \uC774\uB984:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=\uD30C\uC77C \uC720\uD615:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=\uD55C \uB808\uBCA8 \uC704\uB85C
 FileChooser.upFolderAccessibleName=\uC704\uB85C
 FileChooser.homeFolderToolTipText=\uD648
--- a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_pt_BR.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_pt_BR.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Consultar Em:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Salvar Em:
 FileChooser.fileNameLabelText=Nome do Arquivo:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Nome da pasta:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Arquivos do Tipo:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Um N\u00EDvel Acima
 FileChooser.upFolderAccessibleName=Acima
 FileChooser.homeFolderToolTipText=In\u00EDcio
--- a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_sv.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_sv.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=Leta i:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=Spara i:
 FileChooser.fileNameLabelText=Filnamn:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=Mapp:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=Filformat:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=Upp en niv\u00E5
 FileChooser.upFolderAccessibleName=Upp
 FileChooser.homeFolderToolTipText=Hem
--- a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_CN.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_CN.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=\u67E5\u770B:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=\u4FDD\u5B58:
 FileChooser.fileNameLabelText=\u6587\u4EF6\u540D:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=\u6587\u4EF6\u5939\u540D:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=\u6587\u4EF6\u7C7B\u578B:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=\u5411\u4E0A\u4E00\u7EA7
 FileChooser.upFolderAccessibleName=\u5411\u4E0A
 FileChooser.homeFolderToolTipText=\u4E3B\u76EE\u5F55
--- a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_TW.properties	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_TW.properties	Wed Jul 05 17:50:47 2017 +0200
@@ -19,10 +19,14 @@
 ############ FILE CHOOSER STRINGS #############
 
 FileChooser.lookInLabelText=\u67E5\u8A62:
+FileChooser.lookInLabelMnemonic=73
 FileChooser.saveInLabelText=\u5132\u5B58\u65BC:
 FileChooser.fileNameLabelText=\u6A94\u6848\u540D\u7A31:
+FileChooser.fileNameLabelMnemonic=78
 FileChooser.folderNameLabelText=\u8CC7\u6599\u593E\u540D\u7A31:
+FileChooser.folderNameLabelMnemonic=78
 FileChooser.filesOfTypeLabelText=\u6A94\u6848\u985E\u578B:
+FileChooser.filesOfTypeLabelMnemonic=84
 FileChooser.upFolderToolTipText=\u5F80\u4E0A\u4E00\u5C64
 FileChooser.upFolderAccessibleName=\u5F80\u4E0A
 FileChooser.homeFolderToolTipText=\u4E3B\u76EE\u9304
--- a/jdk/src/share/classes/java/awt/BufferCapabilities.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/BufferCapabilities.java	Wed Jul 05 17:50:47 2017 +0200
@@ -137,7 +137,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // Since we implement Cloneable, this should never happen
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/awt/Component.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/Component.java	Wed Jul 05 17:50:47 2017 +0200
@@ -3776,11 +3776,10 @@
             createBufferStrategy(numBuffers, bufferCaps);
             return; // Success
         } catch (AWTException e) {
-            // Failed
-        }
-        // Code should never reach here (an unaccelerated blitting
-        // strategy should always work)
-        throw new InternalError("Could not create a buffer strategy");
+            // Code should never reach here (an unaccelerated blitting
+            // strategy should always work)
+            throw new InternalError("Could not create a buffer strategy", e);
+        }
     }
 
     /**
@@ -7910,7 +7909,7 @@
                 res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_BACKWARD);
             }
         }
-        if (!res) {
+        if (clearOnFailure && !res) {
             if (focusLog.isLoggable(PlatformLogger.FINER)) {
                 focusLog.finer("clear global focus owner");
             }
--- a/jdk/src/share/classes/java/awt/GridBagConstraints.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/GridBagConstraints.java	Wed Jul 05 17:50:47 2017 +0200
@@ -653,7 +653,7 @@
             return c;
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/awt/ImageCapabilities.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/ImageCapabilities.java	Wed Jul 05 17:50:47 2017 +0200
@@ -74,7 +74,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // Since we implement Cloneable, this should never happen
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/awt/Insets.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/Insets.java	Wed Jul 05 17:50:47 2017 +0200
@@ -177,7 +177,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
     /**
--- a/jdk/src/share/classes/java/awt/JobAttributes.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/JobAttributes.java	Wed Jul 05 17:50:47 2017 +0200
@@ -361,7 +361,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // Since we implement Cloneable, this should never happen
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/awt/PageAttributes.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/PageAttributes.java	Wed Jul 05 17:50:47 2017 +0200
@@ -969,7 +969,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // Since we implement Cloneable, this should never happen
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/awt/RenderingHints.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/RenderingHints.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1276,7 +1276,7 @@
             }
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
 
         return rh;
--- a/jdk/src/share/classes/java/awt/font/TextLayout.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/font/TextLayout.java	Wed Jul 05 17:50:47 2017 +0200
@@ -753,7 +753,7 @@
             return super.clone();
         }
         catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/awt/geom/AffineTransform.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/geom/AffineTransform.java	Wed Jul 05 17:50:47 2017 +0200
@@ -3856,7 +3856,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/awt/geom/CubicCurve2D.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/geom/CubicCurve2D.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1569,7 +1569,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 }
--- a/jdk/src/share/classes/java/awt/geom/Dimension2D.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/geom/Dimension2D.java	Wed Jul 05 17:50:47 2017 +0200
@@ -108,7 +108,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 }
--- a/jdk/src/share/classes/java/awt/geom/Line2D.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/geom/Line2D.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1122,7 +1122,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 }
--- a/jdk/src/share/classes/java/awt/geom/Point2D.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/geom/Point2D.java	Wed Jul 05 17:50:47 2017 +0200
@@ -393,7 +393,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/awt/geom/QuadCurve2D.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/geom/QuadCurve2D.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1395,7 +1395,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 }
--- a/jdk/src/share/classes/java/awt/geom/RectangularShape.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/geom/RectangularShape.java	Wed Jul 05 17:50:47 2017 +0200
@@ -391,7 +391,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 }
--- a/jdk/src/share/classes/java/awt/image/ImageFilter.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/image/ImageFilter.java	Wed Jul 05 17:50:47 2017 +0200
@@ -252,7 +252,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 }
--- a/jdk/src/share/classes/java/awt/image/Kernel.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/awt/image/Kernel.java	Wed Jul 05 17:50:47 2017 +0200
@@ -147,7 +147,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 }
--- a/jdk/src/share/classes/java/io/ObjectStreamClass.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/io/ObjectStreamClass.java	Wed Jul 05 17:50:47 2017 +0200
@@ -478,7 +478,7 @@
             fieldRefl = getReflector(fields, this);
         } catch (InvalidClassException ex) {
             // field mismatches impossible when matching local fields vs. self
-            throw new InternalError();
+            throw new InternalError(ex);
         }
 
         if (deserializeEx == null) {
@@ -941,7 +941,7 @@
                 return cons.newInstance();
             } catch (IllegalAccessException ex) {
                 // should not occur, as access checks have been suppressed
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         } else {
             throw new UnsupportedOperationException();
@@ -969,7 +969,7 @@
                 }
             } catch (IllegalAccessException ex) {
                 // should not occur, as access checks have been suppressed
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         } else {
             throw new UnsupportedOperationException();
@@ -1000,7 +1000,7 @@
                 }
             } catch (IllegalAccessException ex) {
                 // should not occur, as access checks have been suppressed
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         } else {
             throw new UnsupportedOperationException();
@@ -1028,7 +1028,7 @@
                 }
             } catch (IllegalAccessException ex) {
                 // should not occur, as access checks have been suppressed
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         } else {
             throw new UnsupportedOperationException();
@@ -1053,11 +1053,11 @@
                     throw (ObjectStreamException) th;
                 } else {
                     throwMiscException(th);
-                    throw new InternalError();  // never reached
+                    throw new InternalError(th);  // never reached
                 }
             } catch (IllegalAccessException ex) {
                 // should not occur, as access checks have been suppressed
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         } else {
             throw new UnsupportedOperationException();
@@ -1082,11 +1082,11 @@
                     throw (ObjectStreamException) th;
                 } else {
                     throwMiscException(th);
-                    throw new InternalError();  // never reached
+                    throw new InternalError(th);  // never reached
                 }
             } catch (IllegalAccessException ex) {
                 // should not occur, as access checks have been suppressed
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         } else {
             throw new UnsupportedOperationException();
@@ -1774,7 +1774,7 @@
             }
             return hash;
         } catch (IOException ex) {
-            throw new InternalError();
+            throw new InternalError(ex);
         } catch (NoSuchAlgorithmException ex) {
             throw new SecurityException(ex.getMessage());
         }
--- a/jdk/src/share/classes/java/lang/CharacterName.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/lang/CharacterName.java	Wed Jul 05 17:50:47 2017 +0200
@@ -83,7 +83,7 @@
             dis.readFully(strPool);
             refStrPool = new SoftReference<>(strPool);
         } catch (Exception x) {
-            throw new InternalError(x.getMessage());
+            throw new InternalError(x.getMessage(), x);
         } finally {
             try {
                 if (dis != null)
--- a/jdk/src/share/classes/java/lang/Class.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/lang/Class.java	Wed Jul 05 17:50:47 2017 +0200
@@ -974,8 +974,7 @@
                 descriptor      = (String)   enclosingInfo[2];
                 assert((name != null && descriptor != null) || name == descriptor);
             } catch (ClassCastException cce) {
-                throw (InternalError)
-                    new InternalError("Invalid type in enclosing method information").initCause(cce);
+                throw new InternalError("Invalid type in enclosing method information", cce);
             }
         }
 
@@ -1241,8 +1240,7 @@
         try {
             return getName().substring(enclosingClass.getName().length());
         } catch (IndexOutOfBoundsException ex) {
-            throw (InternalError)
-                new InternalError("Malformed class name").initCause(ex);
+            throw new InternalError("Malformed class name", ex);
         }
     }
 
--- a/jdk/src/share/classes/java/lang/invoke/CallSite.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/CallSite.java	Wed Jul 05 17:50:47 2017 +0200
@@ -27,7 +27,6 @@
 
 import sun.invoke.empty.Empty;
 import sun.misc.Unsafe;
-import static java.lang.invoke.MethodHandleStatics.*;
 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
 
 /**
@@ -244,8 +243,8 @@
         try {
             GET_TARGET = IMPL_LOOKUP.
                 findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
-        } catch (ReflectiveOperationException ignore) {
-            throw new InternalError();
+        } catch (ReflectiveOperationException e) {
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/lang/invoke/Invokers.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/Invokers.java	Wed Jul 05 17:50:47 2017 +0200
@@ -88,7 +88,7 @@
         try {
             invoker = IMPL_LOOKUP.findVirtual(MethodHandle.class, name, targetType);
         } catch (ReflectiveOperationException ex) {
-            throw new InternalError("JVM cannot find invoker for "+targetType);
+            throw new InternalError("JVM cannot find invoker for "+targetType, ex);
         }
         assert(invokerType(targetType) == invoker.type());
         assert(!invoker.isVarargsCollector());
--- a/jdk/src/share/classes/java/lang/invoke/MemberName.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MemberName.java	Wed Jul 05 17:50:47 2017 +0200
@@ -382,7 +382,7 @@
         try {
             return (MemberName) super.clone();
         } catch (CloneNotSupportedException ex) {
-            throw new InternalError();
+            throw new InternalError(ex);
         }
      }
 
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java	Wed Jul 05 17:50:47 2017 +0200
@@ -108,9 +108,7 @@
         return new IllegalArgumentException(message(message, obj, obj2));
     }
     /*non-public*/ static Error uncaughtException(Exception ex) {
-        Error err = new InternalError("uncaught exception");
-        err.initCause(ex);
-        return err;
+        throw new InternalError("uncaught exception", ex);
     }
     private static String message(String message, Object obj) {
         if (obj != null)  message = message + ": " + obj;
--- a/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java	Wed Jul 05 17:50:47 2017 +0200
@@ -461,7 +461,7 @@
             // Trigger adapter creation.
             genericInvoker = InvokeGeneric.generalInvokerOf(erasedType);
         } catch (Exception ex) {
-            Error err = new InternalError("Exception while resolving inexact invoke");
+            Error err = new InternalError("Exception while resolving inexact invoke", ex);
             err.initCause(ex);
             throw err;
         }
--- a/jdk/src/share/classes/java/lang/reflect/Proxy.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java	Wed Jul 05 17:50:47 2017 +0200
@@ -610,7 +610,7 @@
                  IllegalAccessException |
                  InstantiationException |
                  InvocationTargetException e) {
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 
--- a/jdk/src/share/classes/java/lang/reflect/TypeVariable.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/TypeVariable.java	Wed Jul 05 17:50:47 2017 +0200
@@ -48,7 +48,7 @@
  *
  * @since 1.5
  */
-public interface TypeVariable<D extends GenericDeclaration> extends Type {
+public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
     /**
      * Returns an array of {@code Type} objects representing the
      * upper bound(s) of this type variable.  Note that if no upper bound is
--- a/jdk/src/share/classes/java/math/BigDecimal.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/math/BigDecimal.java	Wed Jul 05 17:50:47 2017 +0200
@@ -215,6 +215,7 @@
  * @author  Josh Bloch
  * @author  Mike Cowlishaw
  * @author  Joseph D. Darcy
+ * @author  Sergey V. Kuksenko
  */
 public class BigDecimal extends Number implements Comparable<BigDecimal> {
     /**
@@ -224,7 +225,7 @@
      * @serial
      * @see #unscaledValue
      */
-    private volatile BigInteger intVal;
+    private final BigInteger intVal;
 
     /**
      * The scale of this BigDecimal, as returned by {@link #scale}.
@@ -232,8 +233,9 @@
      * @serial
      * @see #scale
      */
-    private int scale;  // Note: this may have any value, so
-                        // calculations must be done in longs
+    private final int scale;  // Note: this may have any value, so
+                              // calculations must be done in longs
+
     /**
      * The number of decimal digits in this BigDecimal, or 0 if the
      * number of digits are not known (lookaside information).  If
@@ -256,19 +258,19 @@
      */
     static final long INFLATED = Long.MIN_VALUE;
 
+    private static final BigInteger INFLATED_BIGINT = BigInteger.valueOf(INFLATED);
+
     /**
      * If the absolute value of the significand of this BigDecimal is
      * less than or equal to {@code Long.MAX_VALUE}, the value can be
      * compactly stored in this field and used in computations.
      */
-    private transient long intCompact;
+    private final transient long intCompact;
 
     // All 18-digit base ten strings fit into a long; not all 19-digit
     // strings will
     private static final int MAX_COMPACT_DIGITS = 18;
 
-    private static final int MAX_BIGINT_BITS = 62;
-
     /* Appease the serialization gods */
     private static final long serialVersionUID = 6108874887143696463L;
 
@@ -282,17 +284,17 @@
 
     // Cache of common small BigDecimal values.
     private static final BigDecimal zeroThroughTen[] = {
-        new BigDecimal(BigInteger.ZERO,         0,  0, 1),
-        new BigDecimal(BigInteger.ONE,          1,  0, 1),
-        new BigDecimal(BigInteger.valueOf(2),   2,  0, 1),
-        new BigDecimal(BigInteger.valueOf(3),   3,  0, 1),
-        new BigDecimal(BigInteger.valueOf(4),   4,  0, 1),
-        new BigDecimal(BigInteger.valueOf(5),   5,  0, 1),
-        new BigDecimal(BigInteger.valueOf(6),   6,  0, 1),
-        new BigDecimal(BigInteger.valueOf(7),   7,  0, 1),
-        new BigDecimal(BigInteger.valueOf(8),   8,  0, 1),
-        new BigDecimal(BigInteger.valueOf(9),   9,  0, 1),
-        new BigDecimal(BigInteger.TEN,          10, 0, 2),
+        new BigDecimal(BigInteger.ZERO,       0,  0, 1),
+        new BigDecimal(BigInteger.ONE,        1,  0, 1),
+        new BigDecimal(BigInteger.valueOf(2), 2,  0, 1),
+        new BigDecimal(BigInteger.valueOf(3), 3,  0, 1),
+        new BigDecimal(BigInteger.valueOf(4), 4,  0, 1),
+        new BigDecimal(BigInteger.valueOf(5), 5,  0, 1),
+        new BigDecimal(BigInteger.valueOf(6), 6,  0, 1),
+        new BigDecimal(BigInteger.valueOf(7), 7,  0, 1),
+        new BigDecimal(BigInteger.valueOf(8), 8,  0, 1),
+        new BigDecimal(BigInteger.valueOf(9), 9,  0, 1),
+        new BigDecimal(BigInteger.TEN,        10, 0, 2),
     };
 
     // Cache of zero scaled by 0 - 15
@@ -378,178 +380,7 @@
      * @since  1.5
      */
     public BigDecimal(char[] in, int offset, int len) {
-        // protect against huge length.
-        if (offset+len > in.length || offset < 0)
-            throw new NumberFormatException();
-        // This is the primary string to BigDecimal constructor; all
-        // incoming strings end up here; it uses explicit (inline)
-        // parsing for speed and generates at most one intermediate
-        // (temporary) object (a char[] array) for non-compact case.
-
-        // Use locals for all fields values until completion
-        int prec = 0;                 // record precision value
-        int scl = 0;                  // record scale value
-        long rs = 0;                  // the compact value in long
-        BigInteger rb = null;         // the inflated value in BigInteger
-
-        // use array bounds checking to handle too-long, len == 0,
-        // bad offset, etc.
-        try {
-            // handle the sign
-            boolean isneg = false;          // assume positive
-            if (in[offset] == '-') {
-                isneg = true;               // leading minus means negative
-                offset++;
-                len--;
-            } else if (in[offset] == '+') { // leading + allowed
-                offset++;
-                len--;
-            }
-
-            // should now be at numeric part of the significand
-            boolean dot = false;             // true when there is a '.'
-            int cfirst = offset;             // record start of integer
-            long exp = 0;                    // exponent
-            char c;                          // current character
-
-            boolean isCompact = (len <= MAX_COMPACT_DIGITS);
-            // integer significand array & idx is the index to it. The array
-            // is ONLY used when we can't use a compact representation.
-            char coeff[] = isCompact ? null : new char[len];
-            int idx = 0;
-
-            for (; len > 0; offset++, len--) {
-                c = in[offset];
-                // have digit
-                if ((c >= '0' && c <= '9') || Character.isDigit(c)) {
-                    // First compact case, we need not to preserve the character
-                    // and we can just compute the value in place.
-                    if (isCompact) {
-                        int digit = Character.digit(c, 10);
-                        if (digit == 0) {
-                            if (prec == 0)
-                                prec = 1;
-                            else if (rs != 0) {
-                                rs *= 10;
-                                ++prec;
-                            } // else digit is a redundant leading zero
-                        } else {
-                            if (prec != 1 || rs != 0)
-                                ++prec; // prec unchanged if preceded by 0s
-                            rs = rs * 10 + digit;
-                        }
-                    } else { // the unscaled value is likely a BigInteger object.
-                        if (c == '0' || Character.digit(c, 10) == 0) {
-                            if (prec == 0) {
-                                coeff[idx] = c;
-                                prec = 1;
-                            } else if (idx != 0) {
-                                coeff[idx++] = c;
-                                ++prec;
-                            } // else c must be a redundant leading zero
-                        } else {
-                            if (prec != 1 || idx != 0)
-                                ++prec; // prec unchanged if preceded by 0s
-                            coeff[idx++] = c;
-                        }
-                    }
-                    if (dot)
-                        ++scl;
-                    continue;
-                }
-                // have dot
-                if (c == '.') {
-                    // have dot
-                    if (dot)         // two dots
-                        throw new NumberFormatException();
-                    dot = true;
-                    continue;
-                }
-                // exponent expected
-                if ((c != 'e') && (c != 'E'))
-                    throw new NumberFormatException();
-                offset++;
-                c = in[offset];
-                len--;
-                boolean negexp = (c == '-');
-                // optional sign
-                if (negexp || c == '+') {
-                    offset++;
-                    c = in[offset];
-                    len--;
-                }
-                if (len <= 0)    // no exponent digits
-                    throw new NumberFormatException();
-                // skip leading zeros in the exponent
-                while (len > 10 && Character.digit(c, 10) == 0) {
-                    offset++;
-                    c = in[offset];
-                    len--;
-                }
-                if (len > 10)  // too many nonzero exponent digits
-                    throw new NumberFormatException();
-                // c now holds first digit of exponent
-                for (;; len--) {
-                    int v;
-                    if (c >= '0' && c <= '9') {
-                        v = c - '0';
-                    } else {
-                        v = Character.digit(c, 10);
-                        if (v < 0)            // not a digit
-                            throw new NumberFormatException();
-                    }
-                    exp = exp * 10 + v;
-                    if (len == 1)
-                        break;               // that was final character
-                    offset++;
-                    c = in[offset];
-                }
-                if (negexp)                  // apply sign
-                    exp = -exp;
-                // Next test is required for backwards compatibility
-                if ((int)exp != exp)         // overflow
-                    throw new NumberFormatException();
-                break;                       // [saves a test]
-            }
-            // here when no characters left
-            if (prec == 0)              // no digits found
-                throw new NumberFormatException();
-
-            // Adjust scale if exp is not zero.
-            if (exp != 0) {                  // had significant exponent
-                // Can't call checkScale which relies on proper fields value
-                long adjustedScale = scl - exp;
-                if (adjustedScale > Integer.MAX_VALUE ||
-                    adjustedScale < Integer.MIN_VALUE)
-                    throw new NumberFormatException("Scale out of range.");
-                scl = (int)adjustedScale;
-            }
-
-            // Remove leading zeros from precision (digits count)
-            if (isCompact) {
-                rs = isneg ? -rs : rs;
-            } else {
-                char quick[];
-                if (!isneg) {
-                    quick = (coeff.length != prec) ?
-                        Arrays.copyOf(coeff, prec) : coeff;
-                } else {
-                    quick = new char[prec + 1];
-                    quick[0] = '-';
-                    System.arraycopy(coeff, 0, quick, 1, prec);
-                }
-                rb = new BigInteger(quick);
-                rs = compactValFor(rb);
-            }
-        } catch (ArrayIndexOutOfBoundsException e) {
-            throw new NumberFormatException();
-        } catch (NegativeArraySizeException e) {
-            throw new NumberFormatException();
-        }
-        this.scale = scl;
-        this.precision = prec;
-        this.intCompact = rs;
-        this.intVal = (rs != INFLATED) ? null : rb;
+        this(in,offset,len,MathContext.UNLIMITED);
     }
 
     /**
@@ -576,9 +407,254 @@
      * @since  1.5
      */
     public BigDecimal(char[] in, int offset, int len, MathContext mc) {
-        this(in, offset, len);
-        if (mc.precision > 0)
-            roundThis(mc);
+        // protect against huge length.
+        if (offset + len > in.length || offset < 0)
+            throw new NumberFormatException("Bad offset or len arguments for char[] input.");
+        // This is the primary string to BigDecimal constructor; all
+        // incoming strings end up here; it uses explicit (inline)
+        // parsing for speed and generates at most one intermediate
+        // (temporary) object (a char[] array) for non-compact case.
+
+        // Use locals for all fields values until completion
+        int prec = 0;                 // record precision value
+        int scl = 0;                  // record scale value
+        long rs = 0;                  // the compact value in long
+        BigInteger rb = null;         // the inflated value in BigInteger
+        // use array bounds checking to handle too-long, len == 0,
+        // bad offset, etc.
+        try {
+            // handle the sign
+            boolean isneg = false;          // assume positive
+            if (in[offset] == '-') {
+                isneg = true;               // leading minus means negative
+                offset++;
+                len--;
+            } else if (in[offset] == '+') { // leading + allowed
+                offset++;
+                len--;
+            }
+
+            // should now be at numeric part of the significand
+            boolean dot = false;             // true when there is a '.'
+            long exp = 0;                    // exponent
+            char c;                          // current character
+            boolean isCompact = (len <= MAX_COMPACT_DIGITS);
+            // integer significand array & idx is the index to it. The array
+            // is ONLY used when we can't use a compact representation.
+            int idx = 0;
+            if (isCompact) {
+                // First compact case, we need not to preserve the character
+                // and we can just compute the value in place.
+                for (; len > 0; offset++, len--) {
+                    c = in[offset];
+                    if ((c == '0')) { // have zero
+                        if (prec == 0)
+                            prec = 1;
+                        else if (rs != 0) {
+                            rs *= 10;
+                            ++prec;
+                        } // else digit is a redundant leading zero
+                        if (dot)
+                            ++scl;
+                    } else if ((c >= '1' && c <= '9')) { // have digit
+                        int digit = c - '0';
+                        if (prec != 1 || rs != 0)
+                            ++prec; // prec unchanged if preceded by 0s
+                        rs = rs * 10 + digit;
+                        if (dot)
+                            ++scl;
+                    } else if (c == '.') {   // have dot
+                        // have dot
+                        if (dot) // two dots
+                            throw new NumberFormatException();
+                        dot = true;
+                    } else if (Character.isDigit(c)) { // slow path
+                        int digit = Character.digit(c, 10);
+                        if (digit == 0) {
+                            if (prec == 0)
+                                prec = 1;
+                            else if (rs != 0) {
+                                rs *= 10;
+                                ++prec;
+                            } // else digit is a redundant leading zero
+                        } else {
+                            if (prec != 1 || rs != 0)
+                                ++prec; // prec unchanged if preceded by 0s
+                            rs = rs * 10 + digit;
+                        }
+                        if (dot)
+                            ++scl;
+                    } else if ((c == 'e') || (c == 'E')) {
+                        exp = parseExp(in, offset, len);
+                        // Next test is required for backwards compatibility
+                        if ((int) exp != exp) // overflow
+                            throw new NumberFormatException();
+                        break; // [saves a test]
+                    } else {
+                        throw new NumberFormatException();
+                    }
+                }
+                if (prec == 0) // no digits found
+                    throw new NumberFormatException();
+                // Adjust scale if exp is not zero.
+                if (exp != 0) { // had significant exponent
+                    scl = adjustScale(scl, exp);
+                }
+                rs = isneg ? -rs : rs;
+                int mcp = mc.precision;
+                int drop = prec - mcp; // prec has range [1, MAX_INT], mcp has range [0, MAX_INT];
+                                       // therefore, this subtract cannot overflow
+                if (mcp > 0 && drop > 0) {  // do rounding
+                    while (drop > 0) {
+                        scl = checkScaleNonZero((long) scl - drop);
+                        rs = divideAndRound(rs, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
+                        prec = longDigitLength(rs);
+                        drop = prec - mcp;
+                    }
+                }
+            } else {
+                char coeff[] = new char[len];
+                for (; len > 0; offset++, len--) {
+                    c = in[offset];
+                    // have digit
+                    if ((c >= '0' && c <= '9') || Character.isDigit(c)) {
+                        // First compact case, we need not to preserve the character
+                        // and we can just compute the value in place.
+                        if (c == '0' || Character.digit(c, 10) == 0) {
+                            if (prec == 0) {
+                                coeff[idx] = c;
+                                prec = 1;
+                            } else if (idx != 0) {
+                                coeff[idx++] = c;
+                                ++prec;
+                            } // else c must be a redundant leading zero
+                        } else {
+                            if (prec != 1 || idx != 0)
+                                ++prec; // prec unchanged if preceded by 0s
+                            coeff[idx++] = c;
+                        }
+                        if (dot)
+                            ++scl;
+                        continue;
+                    }
+                    // have dot
+                    if (c == '.') {
+                        // have dot
+                        if (dot) // two dots
+                            throw new NumberFormatException();
+                        dot = true;
+                        continue;
+                    }
+                    // exponent expected
+                    if ((c != 'e') && (c != 'E'))
+                        throw new NumberFormatException();
+                    exp = parseExp(in, offset, len);
+                    // Next test is required for backwards compatibility
+                    if ((int) exp != exp) // overflow
+                        throw new NumberFormatException();
+                    break; // [saves a test]
+                }
+                // here when no characters left
+                if (prec == 0) // no digits found
+                    throw new NumberFormatException();
+                // Adjust scale if exp is not zero.
+                if (exp != 0) { // had significant exponent
+                    scl = adjustScale(scl, exp);
+                }
+                // Remove leading zeros from precision (digits count)
+                rb = new BigInteger(coeff, isneg ? -1 : 1, prec);
+                rs = compactValFor(rb);
+                int mcp = mc.precision;
+                if (mcp > 0 && (prec > mcp)) {
+                    if (rs == INFLATED) {
+                        int drop = prec - mcp;
+                        while (drop > 0) {
+                            scl = checkScaleNonZero((long) scl - drop);
+                            rb = divideAndRoundByTenPow(rb, drop, mc.roundingMode.oldMode);
+                            rs = compactValFor(rb);
+                            if (rs != INFLATED) {
+                                prec = longDigitLength(rs);
+                                break;
+                            }
+                            prec = bigDigitLength(rb);
+                            drop = prec - mcp;
+                        }
+                    }
+                    if (rs != INFLATED) {
+                        int drop = prec - mcp;
+                        while (drop > 0) {
+                            scl = checkScaleNonZero((long) scl - drop);
+                            rs = divideAndRound(rs, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
+                            prec = longDigitLength(rs);
+                            drop = prec - mcp;
+                        }
+                        rb = null;
+                    }
+                }
+            }
+        } catch (ArrayIndexOutOfBoundsException e) {
+            throw new NumberFormatException();
+        } catch (NegativeArraySizeException e) {
+            throw new NumberFormatException();
+        }
+        this.scale = scl;
+        this.precision = prec;
+        this.intCompact = rs;
+        this.intVal = rb;
+    }
+
+    private int adjustScale(int scl, long exp) {
+        long adjustedScale = scl - exp;
+        if (adjustedScale > Integer.MAX_VALUE || adjustedScale < Integer.MIN_VALUE)
+            throw new NumberFormatException("Scale out of range.");
+        scl = (int) adjustedScale;
+        return scl;
+    }
+
+    /*
+     * parse exponent
+     */
+    private static long parseExp(char[] in, int offset, int len){
+        long exp = 0;
+        offset++;
+        char c = in[offset];
+        len--;
+        boolean negexp = (c == '-');
+        // optional sign
+        if (negexp || c == '+') {
+            offset++;
+            c = in[offset];
+            len--;
+        }
+        if (len <= 0) // no exponent digits
+            throw new NumberFormatException();
+        // skip leading zeros in the exponent
+        while (len > 10 && (c=='0' || (Character.digit(c, 10) == 0))) {
+            offset++;
+            c = in[offset];
+            len--;
+        }
+        if (len > 10) // too many nonzero exponent digits
+            throw new NumberFormatException();
+        // c now holds first digit of exponent
+        for (;; len--) {
+            int v;
+            if (c >= '0' && c <= '9') {
+                v = c - '0';
+            } else {
+                v = Character.digit(c, 10);
+                if (v < 0) // not a digit
+                    throw new NumberFormatException();
+            }
+            exp = exp * 10 + v;
+            if (len == 1)
+                break; // that was final character
+            offset++;
+            c = in[offset];
+        }
+        if (negexp) // apply sign
+            exp = -exp;
+        return exp;
     }
 
     /**
@@ -754,9 +830,7 @@
      * @since  1.5
      */
     public BigDecimal(String val, MathContext mc) {
-        this(val.toCharArray(), 0, val.length());
-        if (mc.precision > 0)
-            roundThis(mc);
+        this(val.toCharArray(), 0, val.length(), mc);
     }
 
     /**
@@ -804,49 +878,7 @@
      * @throws NumberFormatException if {@code val} is infinite or NaN.
      */
     public BigDecimal(double val) {
-        if (Double.isInfinite(val) || Double.isNaN(val))
-            throw new NumberFormatException("Infinite or NaN");
-
-        // Translate the double into sign, exponent and significand, according
-        // to the formulae in JLS, Section 20.10.22.
-        long valBits = Double.doubleToLongBits(val);
-        int sign = ((valBits >> 63)==0 ? 1 : -1);
-        int exponent = (int) ((valBits >> 52) & 0x7ffL);
-        long significand = (exponent==0 ? (valBits & ((1L<<52) - 1)) << 1
-                            : (valBits & ((1L<<52) - 1)) | (1L<<52));
-        exponent -= 1075;
-        // At this point, val == sign * significand * 2**exponent.
-
-        /*
-         * Special case zero to supress nonterminating normalization
-         * and bogus scale calculation.
-         */
-        if (significand == 0) {
-            intVal = BigInteger.ZERO;
-            intCompact = 0;
-            precision = 1;
-            return;
-        }
-
-        // Normalize
-        while((significand & 1) == 0) {    //  i.e., significand is even
-            significand >>= 1;
-            exponent++;
-        }
-
-        // Calculate intVal and scale
-        long s = sign * significand;
-        BigInteger b;
-        if (exponent < 0) {
-            b = BigInteger.valueOf(5).pow(-exponent).multiply(s);
-            scale = -exponent;
-        } else if (exponent > 0) {
-            b = BigInteger.valueOf(2).pow(exponent).multiply(s);
-        } else {
-            b = BigInteger.valueOf(s);
-        }
-        intCompact = compactValFor(b);
-        intVal = (intCompact != INFLATED) ? null : b;
+        this(val,MathContext.UNLIMITED);
     }
 
     /**
@@ -868,9 +900,85 @@
      * @since  1.5
      */
     public BigDecimal(double val, MathContext mc) {
-        this(val);
-        if (mc.precision > 0)
-            roundThis(mc);
+        if (Double.isInfinite(val) || Double.isNaN(val))
+            throw new NumberFormatException("Infinite or NaN");
+        // Translate the double into sign, exponent and significand, according
+        // to the formulae in JLS, Section 20.10.22.
+        long valBits = Double.doubleToLongBits(val);
+        int sign = ((valBits >> 63) == 0 ? 1 : -1);
+        int exponent = (int) ((valBits >> 52) & 0x7ffL);
+        long significand = (exponent == 0
+                ? (valBits & ((1L << 52) - 1)) << 1
+                : (valBits & ((1L << 52) - 1)) | (1L << 52));
+        exponent -= 1075;
+        // At this point, val == sign * significand * 2**exponent.
+
+        /*
+         * Special case zero to supress nonterminating normalization and bogus
+         * scale calculation.
+         */
+        if (significand == 0) {
+            this.intVal = BigInteger.ZERO;
+            this.scale = 0;
+            this.intCompact = 0;
+            this.precision = 1;
+            return;
+        }
+        // Normalize
+        while ((significand & 1) == 0) { // i.e., significand is even
+            significand >>= 1;
+            exponent++;
+        }
+        int scale = 0;
+        // Calculate intVal and scale
+        BigInteger intVal;
+        long compactVal = sign * significand;
+        if (exponent == 0) {
+            intVal = (compactVal == INFLATED) ? INFLATED_BIGINT : null;
+        } else {
+            if (exponent < 0) {
+                intVal = BigInteger.valueOf(5).pow(-exponent).multiply(compactVal);
+                scale = -exponent;
+            } else { //  (exponent > 0)
+                intVal = BigInteger.valueOf(2).pow(exponent).multiply(compactVal);
+            }
+            compactVal = compactValFor(intVal);
+        }
+        int prec = 0;
+        int mcp = mc.precision;
+        if (mcp > 0) { // do rounding
+            int mode = mc.roundingMode.oldMode;
+            int drop;
+            if (compactVal == INFLATED) {
+                prec = bigDigitLength(intVal);
+                drop = prec - mcp;
+                while (drop > 0) {
+                    scale = checkScaleNonZero((long) scale - drop);
+                    intVal = divideAndRoundByTenPow(intVal, drop, mode);
+                    compactVal = compactValFor(intVal);
+                    if (compactVal != INFLATED) {
+                        break;
+                    }
+                    prec = bigDigitLength(intVal);
+                    drop = prec - mcp;
+                }
+            }
+            if (compactVal != INFLATED) {
+                prec = longDigitLength(compactVal);
+                drop = prec - mcp;
+                while (drop > 0) {
+                    scale = checkScaleNonZero((long) scale - drop);
+                    compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
+                    prec = longDigitLength(compactVal);
+                    drop = prec - mcp;
+                }
+                intVal = null;
+            }
+        }
+        this.intVal = intVal;
+        this.intCompact = compactVal;
+        this.scale = scale;
+        this.precision = prec;
     }
 
     /**
@@ -881,8 +989,9 @@
      *            {@code BigDecimal}.
      */
     public BigDecimal(BigInteger val) {
+        scale = 0;
+        intVal = val;
         intCompact = compactValFor(val);
-        intVal = (intCompact != INFLATED) ? null : val;
     }
 
     /**
@@ -898,9 +1007,7 @@
      * @since  1.5
      */
     public BigDecimal(BigInteger val, MathContext mc) {
-        this(val);
-        if (mc.precision > 0)
-            roundThis(mc);
+        this(val,0,mc);
     }
 
     /**
@@ -914,7 +1021,8 @@
      */
     public BigDecimal(BigInteger unscaledVal, int scale) {
         // Negative scales are now allowed
-        this(unscaledVal);
+        this.intVal = unscaledVal;
+        this.intCompact = compactValFor(unscaledVal);
         this.scale = scale;
     }
 
@@ -934,10 +1042,41 @@
      * @since  1.5
      */
     public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
-        this(unscaledVal);
+        long compactVal = compactValFor(unscaledVal);
+        int mcp = mc.precision;
+        int prec = 0;
+        if (mcp > 0) { // do rounding
+            int mode = mc.roundingMode.oldMode;
+            if (compactVal == INFLATED) {
+                prec = bigDigitLength(unscaledVal);
+                int drop = prec - mcp;
+                while (drop > 0) {
+                    scale = checkScaleNonZero((long) scale - drop);
+                    unscaledVal = divideAndRoundByTenPow(unscaledVal, drop, mode);
+                    compactVal = compactValFor(unscaledVal);
+                    if (compactVal != INFLATED) {
+                        break;
+                    }
+                    prec = bigDigitLength(unscaledVal);
+                    drop = prec - mcp;
+                }
+            }
+            if (compactVal != INFLATED) {
+                prec = longDigitLength(compactVal);
+                int drop = prec - mcp;     // drop can't be more than 18
+                while (drop > 0) {
+                    scale = checkScaleNonZero((long) scale - drop);
+                    compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mode);
+                    prec = longDigitLength(compactVal);
+                    drop = prec - mcp;
+                }
+                unscaledVal = null;
+            }
+        }
+        this.intVal = unscaledVal;
+        this.intCompact = compactVal;
         this.scale = scale;
-        if (mc.precision > 0)
-            roundThis(mc);
+        this.precision = prec;
     }
 
     /**
@@ -949,7 +1088,9 @@
      * @since  1.5
      */
     public BigDecimal(int val) {
-        intCompact = val;
+        this.intCompact = val;
+        this.scale = 0;
+        this.intVal = null;
     }
 
     /**
@@ -964,9 +1105,24 @@
      * @since  1.5
      */
     public BigDecimal(int val, MathContext mc) {
-        intCompact = val;
-        if (mc.precision > 0)
-            roundThis(mc);
+        int mcp = mc.precision;
+        long compactVal = val;
+        int scale = 0;
+        int prec = 0;
+        if (mcp > 0) { // do rounding
+            prec = longDigitLength(compactVal);
+            int drop = prec - mcp; // drop can't be more than 18
+            while (drop > 0) {
+                scale = checkScaleNonZero((long) scale - drop);
+                compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
+                prec = longDigitLength(compactVal);
+                drop = prec - mcp;
+            }
+        }
+        this.intVal = null;
+        this.intCompact = compactVal;
+        this.scale = scale;
+        this.precision = prec;
     }
 
     /**
@@ -978,7 +1134,8 @@
      */
     public BigDecimal(long val) {
         this.intCompact = val;
-        this.intVal = (val == INFLATED) ? BigInteger.valueOf(val) : null;
+        this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
+        this.scale = 0;
     }
 
     /**
@@ -993,9 +1150,42 @@
      * @since  1.5
      */
     public BigDecimal(long val, MathContext mc) {
-        this(val);
-        if (mc.precision > 0)
-            roundThis(mc);
+        int mcp = mc.precision;
+        int mode = mc.roundingMode.oldMode;
+        int prec = 0;
+        int scale = 0;
+        BigInteger intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
+        if (mcp > 0) { // do rounding
+            if (val == INFLATED) {
+                prec = 19;
+                int drop = prec - mcp;
+                while (drop > 0) {
+                    scale = checkScaleNonZero((long) scale - drop);
+                    intVal = divideAndRoundByTenPow(intVal, drop, mode);
+                    val = compactValFor(intVal);
+                    if (val != INFLATED) {
+                        break;
+                    }
+                    prec = bigDigitLength(intVal);
+                    drop = prec - mcp;
+                }
+            }
+            if (val != INFLATED) {
+                prec = longDigitLength(val);
+                int drop = prec - mcp;
+                while (drop > 0) {
+                    scale = checkScaleNonZero((long) scale - drop);
+                    val = divideAndRound(val, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
+                    prec = longDigitLength(val);
+                    drop = prec - mcp;
+                }
+                intVal = null;
+            }
+        }
+        this.intVal = intVal;
+        this.intCompact = val;
+        this.scale = scale;
+        this.precision = prec;
     }
 
     // Static Factory Methods
@@ -1016,13 +1206,10 @@
         if (scale == 0)
             return valueOf(unscaledVal);
         else if (unscaledVal == 0) {
-            if (scale > 0 && scale < ZERO_SCALED_BY.length)
-                return ZERO_SCALED_BY[scale];
-            else
-                return new BigDecimal(BigInteger.ZERO, 0, scale, 1);
+            return zeroValueOf(scale);
         }
         return new BigDecimal(unscaledVal == INFLATED ?
-                              BigInteger.valueOf(unscaledVal) : null,
+                              INFLATED_BIGINT : null,
                               unscaledVal, scale, 0);
     }
 
@@ -1041,7 +1228,34 @@
             return zeroThroughTen[(int)val];
         else if (val != INFLATED)
             return new BigDecimal(null, val, 0, 0);
-        return new BigDecimal(BigInteger.valueOf(val), val, 0, 0);
+        return new BigDecimal(INFLATED_BIGINT, val, 0, 0);
+    }
+
+    static BigDecimal valueOf(long unscaledVal, int scale, int prec) {
+        if (scale == 0 && unscaledVal >= 0 && unscaledVal < zeroThroughTen.length) {
+            return zeroThroughTen[(int) unscaledVal];
+        } else if (unscaledVal == 0) {
+            return zeroValueOf(scale);
+        }
+        return new BigDecimal(unscaledVal == INFLATED ? INFLATED_BIGINT : null,
+                unscaledVal, scale, prec);
+    }
+
+    static BigDecimal valueOf(BigInteger intVal, int scale, int prec) {
+        long val = compactValFor(intVal);
+        if (val == 0) {
+            return zeroValueOf(scale);
+        } else if (scale == 0 && val >= 0 && val < zeroThroughTen.length) {
+            return zeroThroughTen[(int) val];
+        }
+        return new BigDecimal(intVal, val, scale, prec);
+    }
+
+    static BigDecimal zeroValueOf(int scale) {
+        if (scale >= 0 && scale < ZERO_SCALED_BY.length)
+            return ZERO_SCALED_BY[scale];
+        else
+            return new BigDecimal(BigInteger.ZERO, 0, scale, 1);
     }
 
     /**
@@ -1079,42 +1293,19 @@
      * @return {@code this + augend}
      */
     public BigDecimal add(BigDecimal augend) {
-        long xs = this.intCompact;
-        long ys = augend.intCompact;
-        BigInteger fst = (xs != INFLATED) ? null : this.intVal;
-        BigInteger snd = (ys != INFLATED) ? null : augend.intVal;
-        int rscale = this.scale;
-
-        long sdiff = (long)rscale - augend.scale;
-        if (sdiff != 0) {
-            if (sdiff < 0) {
-                int raise = checkScale(-sdiff);
-                rscale = augend.scale;
-                if (xs == INFLATED ||
-                    (xs = longMultiplyPowerTen(xs, raise)) == INFLATED)
-                    fst = bigMultiplyPowerTen(raise);
+        if (this.intCompact != INFLATED) {
+            if ((augend.intCompact != INFLATED)) {
+                return add(this.intCompact, this.scale, augend.intCompact, augend.scale);
             } else {
-                int raise = augend.checkScale(sdiff);
-                if (ys == INFLATED ||
-                    (ys = longMultiplyPowerTen(ys, raise)) == INFLATED)
-                    snd = augend.bigMultiplyPowerTen(raise);
+                return add(this.intCompact, this.scale, augend.intVal, augend.scale);
+            }
+        } else {
+            if ((augend.intCompact != INFLATED)) {
+                return add(augend.intCompact, augend.scale, this.intVal, this.scale);
+            } else {
+                return add(this.intVal, this.scale, augend.intVal, augend.scale);
             }
         }
-        if (xs != INFLATED && ys != INFLATED) {
-            long sum = xs + ys;
-            // See "Hacker's Delight" section 2-12 for explanation of
-            // the overflow test.
-            if ( (((sum ^ xs) & (sum ^ ys))) >= 0L) // not overflowed
-                return BigDecimal.valueOf(sum, rscale);
-        }
-        if (fst == null)
-            fst = BigInteger.valueOf(xs);
-        if (snd == null)
-            snd = BigInteger.valueOf(ys);
-        BigInteger sum = fst.add(snd);
-        return (fst.signum == snd.signum) ?
-            new BigDecimal(sum, INFLATED, rscale, 0) :
-            new BigDecimal(sum, rscale);
     }
 
     /**
@@ -1136,10 +1327,6 @@
             return add(augend);
         BigDecimal lhs = this;
 
-        // Could optimize if values are compact
-        this.inflate();
-        augend.inflate();
-
         // If either number is zero then the other number, rounded and
         // scaled if necessary, is used as the result.
         {
@@ -1150,20 +1337,14 @@
                 int preferredScale = Math.max(lhs.scale(), augend.scale());
                 BigDecimal result;
 
-                // Could use a factory for zero instead of a new object
                 if (lhsIsZero && augendIsZero)
-                    return new BigDecimal(BigInteger.ZERO, 0, preferredScale, 0);
-
+                    return zeroValueOf(preferredScale);
                 result = lhsIsZero ? doRound(augend, mc) : doRound(lhs, mc);
 
                 if (result.scale() == preferredScale)
                     return result;
                 else if (result.scale() > preferredScale) {
-                    BigDecimal scaledResult =
-                        new BigDecimal(result.intVal, result.intCompact,
-                                       result.scale, 0);
-                    scaledResult.stripZerosToMatchScale(preferredScale);
-                    return scaledResult;
+                    return stripZerosToMatchScale(result.intVal, result.intCompact, result.scale, preferredScale);
                 } else { // result.scale < preferredScale
                     int precisionDiff = mc.precision - result.precision();
                     int scaleDiff     = preferredScale - result.scale();
@@ -1176,17 +1357,14 @@
             }
         }
 
-        long padding = (long)lhs.scale - augend.scale;
-        if (padding != 0) {        // scales differ; alignment needed
+        long padding = (long) lhs.scale - augend.scale;
+        if (padding != 0) { // scales differ; alignment needed
             BigDecimal arg[] = preAlign(lhs, augend, padding, mc);
             matchScale(arg);
-            lhs    = arg[0];
+            lhs = arg[0];
             augend = arg[1];
         }
-
-        BigDecimal d = new BigDecimal(lhs.inflate().add(augend.inflate()),
-                                      lhs.scale);
-        return doRound(d, mc);
+        return doRound(lhs.inflated().add(augend.inflated()), lhs.scale, mc);
     }
 
     /**
@@ -1211,27 +1389,26 @@
      * that the number of digits of the smaller operand could be
      * reduced even though the significands partially overlapped.
      */
-    private BigDecimal[] preAlign(BigDecimal lhs, BigDecimal augend,
-                                  long padding, MathContext mc) {
+    private BigDecimal[] preAlign(BigDecimal lhs, BigDecimal augend, long padding, MathContext mc) {
         assert padding != 0;
         BigDecimal big;
         BigDecimal small;
 
-        if (padding < 0) {     // lhs is big;   augend is small
-            big   = lhs;
+        if (padding < 0) { // lhs is big; augend is small
+            big = lhs;
             small = augend;
-        } else {               // lhs is small; augend is big
-            big   = augend;
+        } else { // lhs is small; augend is big
+            big = augend;
             small = lhs;
         }
 
         /*
-         * This is the estimated scale of an ulp of the result; it
-         * assumes that the result doesn't have a carry-out on a true
-         * add (e.g. 999 + 1 => 1000) or any subtractive cancellation
-         * on borrowing (e.g. 100 - 1.2 => 98.8)
+         * This is the estimated scale of an ulp of the result; it assumes that
+         * the result doesn't have a carry-out on a true add (e.g. 999 + 1 =>
+         * 1000) or any subtractive cancellation on borrowing (e.g. 100 - 1.2 =>
+         * 98.8)
          */
-        long estResultUlpScale = (long)big.scale - big.precision() + mc.precision;
+        long estResultUlpScale = (long) big.scale - big.precision() + mc.precision;
 
         /*
          * The low-order digit position of big is big.scale().  This
@@ -1242,11 +1419,10 @@
          * disjoint *and* the digit positions of small should not be
          * directly visible in the result.
          */
-        long smallHighDigitPos = (long)small.scale - small.precision() + 1;
-        if (smallHighDigitPos > big.scale + 2 &&         // big and small disjoint
+        long smallHighDigitPos = (long) small.scale - small.precision() + 1;
+        if (smallHighDigitPos > big.scale + 2 && // big and small disjoint
             smallHighDigitPos > estResultUlpScale + 2) { // small digits not visible
-            small = BigDecimal.valueOf(small.signum(),
-                                       this.checkScale(Math.max(big.scale, estResultUlpScale) + 3));
+            small = BigDecimal.valueOf(small.signum(), this.checkScale(Math.max(big.scale, estResultUlpScale) + 3));
         }
 
         // Since addition is symmetric, preserving input order in
@@ -1264,7 +1440,22 @@
      * @return {@code this - subtrahend}
      */
     public BigDecimal subtract(BigDecimal subtrahend) {
-        return add(subtrahend.negate());
+        if (this.intCompact != INFLATED) {
+            if ((subtrahend.intCompact != INFLATED)) {
+                return add(this.intCompact, this.scale, -subtrahend.intCompact, subtrahend.scale);
+            } else {
+                return add(this.intCompact, this.scale, subtrahend.intVal.negate(), subtrahend.scale);
+            }
+        } else {
+            if ((subtrahend.intCompact != INFLATED)) {
+                // Pair of subtrahend values given before pair of
+                // values from this BigDecimal to avoid need for
+                // method overloading on the specialized add method
+                return add(-subtrahend.intCompact, subtrahend.scale, this.intVal, this.scale);
+            } else {
+                return add(this.intVal, this.scale, subtrahend.intVal.negate(), subtrahend.scale);
+            }
+        }
     }
 
     /**
@@ -1282,11 +1473,10 @@
      * @since  1.5
      */
     public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) {
-        BigDecimal nsubtrahend = subtrahend.negate();
         if (mc.precision == 0)
-            return add(nsubtrahend);
+            return subtract(subtrahend);
         // share the special rounding code in add()
-        return add(nsubtrahend, mc);
+        return add(subtrahend.negate(), mc);
     }
 
     /**
@@ -1298,37 +1488,20 @@
      * @return {@code this * multiplicand}
      */
     public BigDecimal multiply(BigDecimal multiplicand) {
-        long x = this.intCompact;
-        long y = multiplicand.intCompact;
-        int productScale = checkScale((long)scale + multiplicand.scale);
-
-        // Might be able to do a more clever check incorporating the
-        // inflated check into the overflow computation.
-        if (x != INFLATED && y != INFLATED) {
-            /*
-             * If the product is not an overflowed value, continue
-             * to use the compact representation.  if either of x or y
-             * is INFLATED, the product should also be regarded as
-             * an overflow. Before using the overflow test suggested in
-             * "Hacker's Delight" section 2-12, we perform quick checks
-             * using the precision information to see whether the overflow
-             * would occur since division is expensive on most CPUs.
-             */
-            long product = x * y;
-            long prec = this.precision() + multiplicand.precision();
-            if (prec < 19 || (prec < 21 && (y == 0 || product / y == x)))
-                return BigDecimal.valueOf(product, productScale);
-            return new BigDecimal(BigInteger.valueOf(x).multiply(y), INFLATED,
-                                  productScale, 0);
+        int productScale = checkScale((long) scale + multiplicand.scale);
+        if (this.intCompact != INFLATED) {
+            if ((multiplicand.intCompact != INFLATED)) {
+                return multiply(this.intCompact, multiplicand.intCompact, productScale);
+            } else {
+                return multiply(this.intCompact, multiplicand.intVal, productScale);
+            }
+        } else {
+            if ((multiplicand.intCompact != INFLATED)) {
+                return multiply(multiplicand.intCompact, this.intVal, productScale);
+            } else {
+                return multiply(this.intVal, multiplicand.intVal, productScale);
+            }
         }
-        BigInteger rb;
-        if (x == INFLATED && y == INFLATED)
-            rb = this.intVal.multiply(multiplicand.intVal);
-        else if (x != INFLATED)
-            rb = multiplicand.intVal.multiply(x);
-        else
-            rb = this.intVal.multiply(y);
-        return new BigDecimal(rb, INFLATED, productScale, 0);
     }
 
     /**
@@ -1345,7 +1518,20 @@
     public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) {
         if (mc.precision == 0)
             return multiply(multiplicand);
-        return doRound(this.multiply(multiplicand), mc);
+        int productScale = checkScale((long) scale + multiplicand.scale);
+        if (this.intCompact != INFLATED) {
+            if ((multiplicand.intCompact != INFLATED)) {
+                return multiplyAndRound(this.intCompact, multiplicand.intCompact, productScale, mc);
+            } else {
+                return multiplyAndRound(this.intCompact, multiplicand.intVal, productScale, mc);
+            }
+        } else {
+            if ((multiplicand.intCompact != INFLATED)) {
+                return multiplyAndRound(multiplicand.intCompact, this.intVal, productScale, mc);
+            } else {
+                return multiplyAndRound(this.intVal, multiplicand.intVal, productScale, mc);
+            }
+        }
     }
 
     /**
@@ -1377,120 +1563,21 @@
      * @see    #ROUND_UNNECESSARY
      */
     public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {
-        /*
-         * IMPLEMENTATION NOTE: This method *must* return a new object
-         * since divideAndRound uses divide to generate a value whose
-         * scale is then modified.
-         */
         if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
             throw new IllegalArgumentException("Invalid rounding mode");
-        /*
-         * Rescale dividend or divisor (whichever can be "upscaled" to
-         * produce correctly scaled quotient).
-         * Take care to detect out-of-range scales
-         */
-        BigDecimal dividend = this;
-        if (checkScale((long)scale + divisor.scale) > this.scale)
-            dividend = this.setScale(scale + divisor.scale, ROUND_UNNECESSARY);
-        else
-            divisor = divisor.setScale(checkScale((long)this.scale - scale),
-                                       ROUND_UNNECESSARY);
-        return divideAndRound(dividend.intCompact, dividend.intVal,
-                              divisor.intCompact, divisor.intVal,
-                              scale, roundingMode, scale);
-    }
-
-    /**
-     * Internally used for division operation. The dividend and divisor are
-     * passed both in {@code long} format and {@code BigInteger} format. The
-     * returned {@code BigDecimal} object is the quotient whose scale is set to
-     * the passed in scale. If the remainder is not zero, it will be rounded
-     * based on the passed in roundingMode. Also, if the remainder is zero and
-     * the last parameter, i.e. preferredScale is NOT equal to scale, the
-     * trailing zeros of the result is stripped to match the preferredScale.
-     */
-    private static BigDecimal divideAndRound(long ldividend, BigInteger bdividend,
-                                             long ldivisor,  BigInteger bdivisor,
-                                             int scale, int roundingMode,
-                                             int preferredScale) {
-        boolean isRemainderZero;       // record remainder is zero or not
-        int qsign;                     // quotient sign
-        long q = 0, r = 0;             // store quotient & remainder in long
-        MutableBigInteger mq = null;   // store quotient
-        MutableBigInteger mr = null;   // store remainder
-        MutableBigInteger mdivisor = null;
-        boolean isLongDivision = (ldividend != INFLATED && ldivisor != INFLATED);
-        if (isLongDivision) {
-            q = ldividend / ldivisor;
-            if (roundingMode == ROUND_DOWN && scale == preferredScale)
-                return new BigDecimal(null, q, scale, 0);
-            r = ldividend % ldivisor;
-            isRemainderZero = (r == 0);
-            qsign = ((ldividend < 0) == (ldivisor < 0)) ? 1 : -1;
+        if (this.intCompact != INFLATED) {
+            if ((divisor.intCompact != INFLATED)) {
+                return divide(this.intCompact, this.scale, divisor.intCompact, divisor.scale, scale, roundingMode);
+            } else {
+                return divide(this.intCompact, this.scale, divisor.intVal, divisor.scale, scale, roundingMode);
+            }
         } else {
-            if (bdividend == null)
-                bdividend = BigInteger.valueOf(ldividend);
-            // Descend into mutables for faster remainder checks
-            MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag);
-            mq = new MutableBigInteger();
-            if (ldivisor != INFLATED) {
-                r = mdividend.divide(ldivisor, mq);
-                isRemainderZero = (r == 0);
-                qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
+            if ((divisor.intCompact != INFLATED)) {
+                return divide(this.intVal, this.scale, divisor.intCompact, divisor.scale, scale, roundingMode);
             } else {
-                mdivisor = new MutableBigInteger(bdivisor.mag);
-                mr = mdividend.divide(mdivisor, mq);
-                isRemainderZero = mr.isZero();
-                qsign = (bdividend.signum != bdivisor.signum) ? -1 : 1;
+                return divide(this.intVal, this.scale, divisor.intVal, divisor.scale, scale, roundingMode);
             }
         }
-        boolean increment = false;
-        if (!isRemainderZero) {
-            int cmpFracHalf;
-            /* Round as appropriate */
-            if (roundingMode == ROUND_UNNECESSARY) {  // Rounding prohibited
-                throw new ArithmeticException("Rounding necessary");
-            } else if (roundingMode == ROUND_UP) {      // Away from zero
-                increment = true;
-            } else if (roundingMode == ROUND_DOWN) {    // Towards zero
-                increment = false;
-            } else if (roundingMode == ROUND_CEILING) { // Towards +infinity
-                increment = (qsign > 0);
-            } else if (roundingMode == ROUND_FLOOR) {   // Towards -infinity
-                increment = (qsign < 0);
-            } else {
-                if (isLongDivision || ldivisor != INFLATED) {
-                    if (r <= HALF_LONG_MIN_VALUE || r > HALF_LONG_MAX_VALUE) {
-                        cmpFracHalf = 1;    // 2 * r can't fit into long
-                    } else {
-                        cmpFracHalf = longCompareMagnitude(2 * r, ldivisor);
-                    }
-                } else {
-                    cmpFracHalf = mr.compareHalf(mdivisor);
-                }
-                if (cmpFracHalf < 0)
-                    increment = false;     // We're closer to higher digit
-                else if (cmpFracHalf > 0)  // We're closer to lower digit
-                    increment = true;
-                else if (roundingMode == ROUND_HALF_UP)
-                    increment = true;
-                else if (roundingMode == ROUND_HALF_DOWN)
-                    increment = false;
-                else  // roundingMode == ROUND_HALF_EVEN, true iff quotient is odd
-                    increment = isLongDivision ? (q & 1L) != 0L : mq.isOdd();
-            }
-        }
-        BigDecimal res;
-        if (isLongDivision)
-            res = new BigDecimal(null, (increment ? q + qsign : q), scale, 0);
-        else {
-            if (increment)
-                mq.add(MutableBigInteger.ONE);
-            res = mq.toBigDecimal(qsign, scale);
-        }
-        if (isRemainderZero && preferredScale != scale)
-            res.stripZerosToMatchScale(preferredScale);
-        return res;
     }
 
     /**
@@ -1541,7 +1628,7 @@
      * @see    #ROUND_UNNECESSARY
      */
     public BigDecimal divide(BigDecimal divisor, int roundingMode) {
-            return this.divide(divisor, scale, roundingMode);
+        return this.divide(divisor, scale, roundingMode);
     }
 
     /**
@@ -1588,15 +1675,11 @@
         }
 
         // Calculate preferred scale
-        int preferredScale = saturateLong((long)this.scale - divisor.scale);
-        if (this.signum() == 0)        // 0/y
-            return (preferredScale >= 0 &&
-                    preferredScale < ZERO_SCALED_BY.length) ?
-                ZERO_SCALED_BY[preferredScale] :
-                BigDecimal.valueOf(0, preferredScale);
+        int preferredScale = saturateLong((long) this.scale - divisor.scale);
+
+        if (this.signum() == 0) // 0/y
+            return zeroValueOf(preferredScale);
         else {
-            this.inflate();
-            divisor.inflate();
             /*
              * If the quotient this/divisor has a terminating decimal
              * expansion, the expansion can have no more than
@@ -1623,7 +1706,6 @@
             // the desired one by removing trailing zeros; since the
             // exact divide method does not have an explicit digit
             // limit, we can add zeros too.
-
             if (preferredScale > quotientScale)
                 return quotient.setScale(preferredScale, ROUND_UNNECESSARY);
 
@@ -1668,38 +1750,23 @@
                 throw new ArithmeticException("Division undefined");  // NaN
             throw new ArithmeticException("Division by zero");
         }
-        if (dividend.signum() == 0)        // 0/y
-            return new BigDecimal(BigInteger.ZERO, 0,
-                                  saturateLong(preferredScale), 1);
-
-        // Normalize dividend & divisor so that both fall into [0.1, 0.999...]
+        if (dividend.signum() == 0) // 0/y
+            return zeroValueOf(saturateLong(preferredScale));
         int xscale = dividend.precision();
         int yscale = divisor.precision();
-        dividend = new BigDecimal(dividend.intVal, dividend.intCompact,
-                                  xscale, xscale);
-        divisor = new BigDecimal(divisor.intVal, divisor.intCompact,
-                                 yscale, yscale);
-        if (dividend.compareMagnitude(divisor) > 0) // satisfy constraint (b)
-            yscale = divisor.scale -= 1;            // [that is, divisor *= 10]
-
-        // In order to find out whether the divide generates the exact result,
-        // we avoid calling the above divide method. 'quotient' holds the
-        // return BigDecimal object whose scale will be set to 'scl'.
-        BigDecimal quotient;
-        int scl = checkScale(preferredScale + yscale - xscale + mcp);
-        if (checkScale((long)mcp + yscale) > xscale)
-            dividend = dividend.setScale(mcp + yscale, ROUND_UNNECESSARY);
-        else
-            divisor = divisor.setScale(checkScale((long)xscale - mcp),
-                                       ROUND_UNNECESSARY);
-        quotient = divideAndRound(dividend.intCompact, dividend.intVal,
-                                  divisor.intCompact, divisor.intVal,
-                                  scl, mc.roundingMode.oldMode,
-                                  checkScale(preferredScale));
-        // doRound, here, only affects 1000000000 case.
-        quotient = doRound(quotient, mc);
-
-        return quotient;
+        if(dividend.intCompact!=INFLATED) {
+            if(divisor.intCompact!=INFLATED) {
+                return divide(dividend.intCompact, xscale, divisor.intCompact, yscale, preferredScale, mc);
+            } else {
+                return divide(dividend.intCompact, xscale, divisor.intVal, yscale, preferredScale, mc);
+            }
+        } else {
+            if(divisor.intCompact!=INFLATED) {
+                return divide(dividend.intVal, xscale, divisor.intCompact, yscale, preferredScale, mc);
+            } else {
+                return divide(dividend.intVal, xscale, divisor.intVal, yscale, preferredScale, mc);
+            }
+        }
     }
 
     /**
@@ -1715,13 +1782,13 @@
      */
     public BigDecimal divideToIntegralValue(BigDecimal divisor) {
         // Calculate preferred scale
-        int preferredScale = saturateLong((long)this.scale - divisor.scale);
+        int preferredScale = saturateLong((long) this.scale - divisor.scale);
         if (this.compareMagnitude(divisor) < 0) {
             // much faster when this << divisor
-            return BigDecimal.valueOf(0, preferredScale);
+            return zeroValueOf(preferredScale);
         }
 
-        if(this.signum() == 0 && divisor.signum() != 0)
+        if (this.signum() == 0 && divisor.signum() != 0)
             return this.setScale(preferredScale, ROUND_UNNECESSARY);
 
         // Perform a divide with enough digits to round to a correct
@@ -1735,13 +1802,14 @@
                                                                    RoundingMode.DOWN));
         if (quotient.scale > 0) {
             quotient = quotient.setScale(0, RoundingMode.DOWN);
-            quotient.stripZerosToMatchScale(preferredScale);
+            quotient = stripZerosToMatchScale(quotient.intVal, quotient.intCompact, quotient.scale, preferredScale);
         }
 
         if (quotient.scale < preferredScale) {
             // pad with zeros if necessary
             quotient = quotient.setScale(preferredScale, ROUND_UNNECESSARY);
         }
+
         return quotient;
     }
 
@@ -1766,8 +1834,8 @@
      * @author Joseph D. Darcy
      */
     public BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc) {
-        if (mc.precision == 0 ||                        // exact result
-            (this.compareMagnitude(divisor) < 0) )      // zero result
+        if (mc.precision == 0 || // exact result
+            (this.compareMagnitude(divisor) < 0)) // zero result
             return divideToIntegralValue(divisor);
 
         // Calculate preferred scale
@@ -1780,8 +1848,7 @@
          * digits.  Next, remove any fractional digits from the
          * quotient and adjust the scale to the preferred value.
          */
-        BigDecimal result = this.
-            divide(divisor, new MathContext(mc.precision, RoundingMode.DOWN));
+        BigDecimal result = this.divide(divisor, new MathContext(mc.precision, RoundingMode.DOWN));
 
         if (result.scale() < 0) {
             /*
@@ -1811,8 +1878,7 @@
             return result.setScale(result.scale() +
                                    Math.min(precisionDiff, preferredScale - result.scale) );
         } else {
-            result.stripZerosToMatchScale(preferredScale);
-            return result;
+            return stripZerosToMatchScale(result.intVal,result.intCompact,result.scale,preferredScale);
         }
     }
 
@@ -1954,8 +2020,7 @@
         // No need to calculate pow(n) if result will over/underflow.
         // Don't attempt to support "supernormal" numbers.
         int newScale = checkScale((long)scale * n);
-        this.inflate();
-        return new BigDecimal(intVal.pow(n), newScale);
+        return new BigDecimal(this.inflated().pow(n), newScale);
     }
 
 
@@ -2016,12 +2081,10 @@
             throw new ArithmeticException("Invalid operation");
         if (n == 0)
             return ONE;                      // x**0 == 1 in X3.274
-        this.inflate();
         BigDecimal lhs = this;
         MathContext workmc = mc;           // working settings
         int mag = Math.abs(n);               // magnitude of n
         if (mc.precision > 0) {
-
             int elength = longDigitLength(mag); // length of n in digits
             if (elength > mc.precision)        // X3.274 rule
                 throw new ArithmeticException("Invalid operation");
@@ -2044,7 +2107,7 @@
                 // else (!seenbit) no point in squaring ONE
         }
         // if negative n, calculate the reciprocal using working precision
-        if (n<0)                          // [hence mc.precision>0]
+        if (n < 0) // [hence mc.precision>0]
             acc=ONE.divide(acc, workmc);
         // round to final precision and strip zeros
         return doRound(acc, mc);
@@ -2083,14 +2146,11 @@
      * @return {@code -this}.
      */
     public BigDecimal negate() {
-        BigDecimal result;
-        if (intCompact != INFLATED)
-            result = BigDecimal.valueOf(-intCompact, scale);
-        else {
-            result = new BigDecimal(intVal.negate(), scale);
-            result.precision = precision;
+        if (intCompact == INFLATED) {
+            return new BigDecimal(intVal.negate(), INFLATED, scale, precision);
+        } else {
+            return valueOf(-intCompact, scale, precision);
         }
-        return result;
     }
 
     /**
@@ -2186,7 +2246,7 @@
             if (s != INFLATED)
                 result = longDigitLength(s);
             else
-                result = bigDigitLength(inflate());
+                result = bigDigitLength(intVal);
             precision = result;
         }
         return result;
@@ -2202,7 +2262,7 @@
      * @since  1.2
      */
     public BigInteger unscaledValue() {
-        return this.inflate();
+        return this.inflated();
     }
 
     // Rounding Modes
@@ -2383,29 +2443,41 @@
         if (newScale == oldScale)        // easy case
             return this;
         if (this.signum() == 0)            // zero can have any scale
-            return BigDecimal.valueOf(0, newScale);
-
-        long rs = this.intCompact;
-        if (newScale > oldScale) {
-            int raise = checkScale((long)newScale - oldScale);
-            BigInteger rb = null;
-            if (rs == INFLATED ||
-                (rs = longMultiplyPowerTen(rs, raise)) == INFLATED)
-                rb = bigMultiplyPowerTen(raise);
-            return new BigDecimal(rb, rs, newScale,
-                                  (precision > 0) ? precision + raise : 0);
+            return zeroValueOf(newScale);
+        if(this.intCompact!=INFLATED) {
+            long rs = this.intCompact;
+            if (newScale > oldScale) {
+                int raise = checkScale((long) newScale - oldScale);
+                if ((rs = longMultiplyPowerTen(rs, raise)) != INFLATED) {
+                    return valueOf(rs,newScale);
+                }
+                BigInteger rb = bigMultiplyPowerTen(raise);
+                return new BigDecimal(rb, INFLATED, newScale, (precision > 0) ? precision + raise : 0);
+            } else {
+                // newScale < oldScale -- drop some digits
+                // Can't predict the precision due to the effect of rounding.
+                int drop = checkScale((long) oldScale - newScale);
+                if (drop < LONG_TEN_POWERS_TABLE.length) {
+                    return divideAndRound(rs, LONG_TEN_POWERS_TABLE[drop], newScale, roundingMode, newScale);
+                } else {
+                    return divideAndRound(this.inflated(), bigTenToThe(drop), newScale, roundingMode, newScale);
+                }
+            }
         } else {
-            // newScale < oldScale -- drop some digits
-            // Can't predict the precision due to the effect of rounding.
-            int drop = checkScale((long)oldScale - newScale);
-            if (drop < LONG_TEN_POWERS_TABLE.length)
-                return divideAndRound(rs, this.intVal,
-                                      LONG_TEN_POWERS_TABLE[drop], null,
-                                      newScale, roundingMode, newScale);
-            else
-                return divideAndRound(rs, this.intVal,
-                                      INFLATED, bigTenToThe(drop),
-                                      newScale, roundingMode, newScale);
+            if (newScale > oldScale) {
+                int raise = checkScale((long) newScale - oldScale);
+                BigInteger rb = bigMultiplyPowerTen(this.intVal,raise);
+                return new BigDecimal(rb, INFLATED, newScale, (precision > 0) ? precision + raise : 0);
+            } else {
+                // newScale < oldScale -- drop some digits
+                // Can't predict the precision due to the effect of rounding.
+                int drop = checkScale((long) oldScale - newScale);
+                if (drop < LONG_TEN_POWERS_TABLE.length)
+                    return divideAndRound(this.intVal, LONG_TEN_POWERS_TABLE[drop], newScale, roundingMode,
+                                          newScale);
+                else
+                    return divideAndRound(this.intVal,  bigTenToThe(drop), newScale, roundingMode, newScale);
+            }
         }
     }
 
@@ -2524,10 +2596,11 @@
      * @since 1.5
      */
     public BigDecimal stripTrailingZeros() {
-        this.inflate();
-        BigDecimal result = new BigDecimal(intVal, scale);
-        result.stripZerosToMatchScale(Long.MIN_VALUE);
-        return result;
+        if(intCompact!=INFLATED) {
+            return createAndStripZerosToMatchScale(intCompact, scale, Long.MIN_VALUE);
+        } else {
+            return createAndStripZerosToMatchScale(intVal, scale, Long.MIN_VALUE);
+        }
     }
 
     // Comparison Operations
@@ -2647,7 +2720,7 @@
         } else if (xs != INFLATED)
             return xs == compactValFor(this.intVal);
 
-        return this.inflate().equals(xDec.inflate());
+        return this.inflated().equals(xDec.inflated());
     }
 
     /**
@@ -2872,13 +2945,38 @@
      * @see #toEngineeringString()
      */
     public String toPlainString() {
-        BigDecimal bd = this;
-        if (bd.scale < 0)
-            bd = bd.setScale(0);
-        bd.inflate();
-        if (bd.scale == 0)      // No decimal point
-            return bd.intVal.toString();
-        return bd.getValueString(bd.signum(), bd.intVal.abs().toString(), bd.scale);
+        if(scale==0) {
+            if(intCompact!=INFLATED) {
+                return Long.toString(intCompact);
+            } else {
+                return intVal.toString();
+            }
+        }
+        if(this.scale<0) { // No decimal point
+            if(signum()==0) {
+                return "0";
+            }
+            int tailingZeros = checkScaleNonZero((-(long)scale));
+            StringBuilder buf;
+            if(intCompact!=INFLATED) {
+                buf = new StringBuilder(20+tailingZeros);
+                buf.append(intCompact);
+            } else {
+                String str = intVal.toString();
+                buf = new StringBuilder(str.length()+tailingZeros);
+                buf.append(str);
+            }
+            for (int i = 0; i < tailingZeros; i++)
+                buf.append('0');
+            return buf.toString();
+        }
+        String str ;
+        if(intCompact!=INFLATED) {
+            str = Long.toString(Math.abs(intCompact));
+        } else {
+            str = intVal.abs().toString();
+        }
+        return getValueString(signum(), str, scale);
     }
 
     /* Returns a digit.digit string */
@@ -2922,7 +3020,7 @@
      */
     public BigInteger toBigInteger() {
         // force to an integer, quietly
-        return this.setScale(0, ROUND_DOWN).inflate();
+        return this.setScale(0, ROUND_DOWN).inflated();
     }
 
     /**
@@ -2937,7 +3035,7 @@
      */
     public BigInteger toBigIntegerExact() {
         // round to an integer, with Exception if decimal part non-0
-        return this.setScale(0, ROUND_UNNECESSARY).inflate();
+        return this.setScale(0, ROUND_UNNECESSARY).inflated();
     }
 
     /**
@@ -2990,7 +3088,7 @@
         BigDecimal num = this.setScale(0, ROUND_UNNECESSARY);
         if (num.precision() >= 19) // need to check carefully
             LongOverflow.check(num);
-        return num.inflate().longValue();
+        return num.inflated().longValue();
     }
 
     private static class LongOverflow {
@@ -3001,9 +3099,9 @@
         private static final BigInteger LONGMAX = BigInteger.valueOf(Long.MAX_VALUE);
 
         public static void check(BigDecimal num) {
-            num.inflate();
-            if ((num.intVal.compareTo(LONGMIN) < 0) ||
-                (num.intVal.compareTo(LONGMAX) > 0))
+            BigInteger intVal = num.inflated();
+            if (intVal.compareTo(LONGMIN) < 0 ||
+                intVal.compareTo(LONGMAX) > 0)
                 throw new java.lang.ArithmeticException("Overflow");
         }
     }
@@ -3107,8 +3205,28 @@
      * @return this {@code BigDecimal} converted to a {@code float}.
      */
     public float floatValue(){
-        if (scale == 0 && intCompact != INFLATED)
+        if(intCompact != INFLATED) {
+            if (scale == 0) {
                 return (float)intCompact;
+            } else {
+                /*
+                 * If both intCompact and the scale can be exactly
+                 * represented as float values, perform a single float
+                 * multiply or divide to compute the (properly
+                 * rounded) result.
+                 */
+                if (Math.abs(intCompact) < 1L<<22 ) {
+                    // Don't have too guard against
+                    // Math.abs(MIN_VALUE) because of outer check
+                    // against INFLATED.
+                    if (scale > 0 && scale < float10pow.length) {
+                        return (float)intCompact / float10pow[scale];
+                    } else if (scale < 0 && scale > -float10pow.length) {
+                        return (float)intCompact * float10pow[-scale];
+                    }
+                }
+            }
+        }
         // Somewhat inefficient, but guaranteed to work.
         return Float.parseFloat(this.toString());
     }
@@ -3130,13 +3248,53 @@
      * @return this {@code BigDecimal} converted to a {@code double}.
      */
     public double doubleValue(){
-        if (scale == 0 && intCompact != INFLATED)
-            return (double)intCompact;
+        if(intCompact != INFLATED) {
+            if (scale == 0) {
+                return (double)intCompact;
+            } else {
+                /*
+                 * If both intCompact and the scale can be exactly
+                 * represented as double values, perform a single
+                 * double multiply or divide to compute the (properly
+                 * rounded) result.
+                 */
+                if (Math.abs(intCompact) < 1L<<52 ) {
+                    // Don't have too guard against
+                    // Math.abs(MIN_VALUE) because of outer check
+                    // against INFLATED.
+                    if (scale > 0 && scale < double10pow.length) {
+                        return (double)intCompact / double10pow[scale];
+                    } else if (scale < 0 && scale > -double10pow.length) {
+                        return (double)intCompact * double10pow[-scale];
+                    }
+                }
+            }
+        }
         // Somewhat inefficient, but guaranteed to work.
         return Double.parseDouble(this.toString());
     }
 
     /**
+     * Powers of 10 which can be represented exactly in {@code
+     * double}.
+     */
+    private static final double double10pow[] = {
+        1.0e0,  1.0e1,  1.0e2,  1.0e3,  1.0e4,  1.0e5,
+        1.0e6,  1.0e7,  1.0e8,  1.0e9,  1.0e10, 1.0e11,
+        1.0e12, 1.0e13, 1.0e14, 1.0e15, 1.0e16, 1.0e17,
+        1.0e18, 1.0e19, 1.0e20, 1.0e21, 1.0e22
+    };
+
+    /**
+     * Powers of 10 which can be represented exactly in {@code
+     * float}.
+     */
+    private static final float float10pow[] = {
+        1.0e0f, 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
+        1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
+    };
+
+    /**
      * Returns the size of an ulp, a unit in the last place, of this
      * {@code BigDecimal}.  An ulp of a nonzero {@code BigDecimal}
      * value is the positive distance between this value and the
@@ -3151,10 +3309,9 @@
      * @since 1.5
      */
     public BigDecimal ulp() {
-        return BigDecimal.valueOf(1, this.scale());
+        return BigDecimal.valueOf(1, this.scale(), 1);
     }
 
-
     // Private class to build a string representation for BigDecimal object.
     // "StringBuilderHelper" is constructed as a thread local variable so it is
     // thread safe. The StringBuilder field acts as a buffer to hold the temporary
@@ -3268,6 +3425,15 @@
             return (intCompact != INFLATED) ?
                 Long.toString(intCompact):
                 intVal.toString();
+        if (scale == 2  &&
+            intCompact >= 0 && intCompact < Integer.MAX_VALUE) {
+            // currency fast path
+            int lowInt = (int)intCompact % 100;
+            int highInt = (int)intCompact / 100;
+            return (Integer.toString(highInt) + '.' +
+                    StringBuilderHelper.DIGIT_TENS[lowInt] +
+                    StringBuilderHelper.DIGIT_ONES[lowInt]) ;
+        }
 
         StringBuilderHelper sbHelper = threadLocalStringBuilderHelper.get();
         char[] coeff;
@@ -3377,7 +3543,7 @@
         tenpow[0] = '1';
         for (int i = 1; i <= n; i++)
             tenpow[i] = '0';
-        return new BigInteger(tenpow);
+        return new BigInteger(tenpow,1, tenpow.length);
     }
 
     /**
@@ -3433,11 +3599,16 @@
         1000000000000000000L   // 18 / 10^18
     };
 
-    private static volatile BigInteger BIG_TEN_POWERS_TABLE[] = {BigInteger.ONE,
-        BigInteger.valueOf(10),       BigInteger.valueOf(100),
-        BigInteger.valueOf(1000),     BigInteger.valueOf(10000),
-        BigInteger.valueOf(100000),   BigInteger.valueOf(1000000),
-        BigInteger.valueOf(10000000), BigInteger.valueOf(100000000),
+    private static volatile BigInteger BIG_TEN_POWERS_TABLE[] = {
+        BigInteger.ONE,
+        BigInteger.valueOf(10),
+        BigInteger.valueOf(100),
+        BigInteger.valueOf(1000),
+        BigInteger.valueOf(10000),
+        BigInteger.valueOf(100000),
+        BigInteger.valueOf(1000000),
+        BigInteger.valueOf(10000000),
+        BigInteger.valueOf(100000000),
         BigInteger.valueOf(1000000000),
         BigInteger.valueOf(10000000000L),
         BigInteger.valueOf(100000000000L),
@@ -3502,7 +3673,7 @@
      */
     private BigInteger bigMultiplyPowerTen(int n) {
         if (n <= 0)
-            return this.inflate();
+            return this.inflated();
 
         if (intCompact != INFLATED)
             return bigTenToThe(n).multiply(intCompact);
@@ -3511,12 +3682,13 @@
     }
 
     /**
-     * Assign appropriate BigInteger to intVal field if intVal is
+     * Returns appropriate BigInteger from intVal field if intVal is
      * null, i.e. the compact representation is in use.
      */
-    private BigInteger inflate() {
-        if (intVal == null)
-            intVal = BigInteger.valueOf(intCompact);
+    private BigInteger inflated() {
+        if (intVal == null) {
+            return BigInteger.valueOf(intCompact);
+        }
         return intVal;
     }
 
@@ -3543,6 +3715,30 @@
         }
     }
 
+    private static class UnsafeHolder {
+        private static final sun.misc.Unsafe unsafe;
+        private static final long intCompactOffset;
+        private static final long intValOffset;
+        static {
+            try {
+                unsafe = sun.misc.Unsafe.getUnsafe();
+                intCompactOffset = unsafe.objectFieldOffset
+                    (BigDecimal.class.getDeclaredField("intCompact"));
+                intValOffset = unsafe.objectFieldOffset
+                    (BigDecimal.class.getDeclaredField("intVal"));
+            } catch (Exception ex) {
+                throw new ExceptionInInitializerError(ex);
+            }
+        }
+        static void setIntCompactVolatile(BigDecimal bd, long val) {
+            unsafe.putLongVolatile(bd, intCompactOffset, val);
+        }
+
+        static void setIntValVolatile(BigDecimal bd, BigInteger val) {
+            unsafe.putObjectVolatile(bd, intValOffset, val);
+        }
+    }
+
     /**
      * Reconstitute the {@code BigDecimal} instance from a stream (that is,
      * deserialize it).
@@ -3559,7 +3755,7 @@
             throw new java.io.StreamCorruptedException(message);
         // [all values of scale are now allowed]
         }
-        intCompact = compactValFor(intVal);
+        UnsafeHolder.setIntCompactVolatile(this, compactValFor(intVal));
     }
 
    /**
@@ -3570,13 +3766,12 @@
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
        // Must inflate to maintain compatible serial form.
-       this.inflate();
-
-       // Write proper fields
+       if (this.intVal == null)
+           UnsafeHolder.setIntValVolatile(this, BigInteger.valueOf(this.intCompact));
+       // Could reset intVal back to null if it has to be set.
        s.defaultWriteObject();
    }
 
-
     /**
      * Returns the length of the absolute value of a {@code long}, in decimal
      * digits.
@@ -3584,36 +3779,29 @@
      * @param x the {@code long}
      * @return the length of the unscaled value, in deciaml digits.
      */
-    private static int longDigitLength(long x) {
+    static int longDigitLength(long x) {
         /*
          * As described in "Bit Twiddling Hacks" by Sean Anderson,
          * (http://graphics.stanford.edu/~seander/bithacks.html)
-         * integer log 10 of x is within 1 of
-         * (1233/4096)* (1 + integer log 2 of x).
-         * The fraction 1233/4096 approximates log10(2). So we first
-         * do a version of log2 (a variant of Long class with
-         * pre-checks and opposite directionality) and then scale and
-         * check against powers table. This is a little simpler in
-         * present context than the version in Hacker's Delight sec
-         * 11-4.  Adding one to bit length allows comparing downward
-         * from the LONG_TEN_POWERS_TABLE that we need anyway.
+         * integer log 10 of x is within 1 of (1233/4096)* (1 +
+         * integer log 2 of x). The fraction 1233/4096 approximates
+         * log10(2). So we first do a version of log2 (a variant of
+         * Long class with pre-checks and opposite directionality) and
+         * then scale and check against powers table. This is a little
+         * simpler in present context than the version in Hacker's
+         * Delight sec 11-4. Adding one to bit length allows comparing
+         * downward from the LONG_TEN_POWERS_TABLE that we need
+         * anyway.
          */
-        assert x != INFLATED;
+        assert x != BigDecimal.INFLATED;
         if (x < 0)
             x = -x;
         if (x < 10) // must screen for 0, might as well 10
             return 1;
-        int n = 64; // not 63, to avoid needing to add 1 later
-        int y = (int)(x >>> 32);
-        if (y == 0) { n -= 32; y = (int)x; }
-        if (y >>> 16 == 0) { n -= 16; y <<= 16; }
-        if (y >>> 24 == 0) { n -=  8; y <<=  8; }
-        if (y >>> 28 == 0) { n -=  4; y <<=  4; }
-        if (y >>> 30 == 0) { n -=  2; y <<=  2; }
-        int r = (((y >>> 31) + n) * 1233) >>> 12;
+        int r = ((64 - Long.numberOfLeadingZeros(x) + 1) * 1233) >>> 12;
         long[] tab = LONG_TEN_POWERS_TABLE;
         // if r >= length, must have max possible digits for long
-        return (r >= tab.length || x < tab[r])? r : r+1;
+        return (r >= tab.length || x < tab[r]) ? r : r + 1;
     }
 
     /**
@@ -3635,41 +3823,6 @@
         return b.compareMagnitude(bigTenToThe(r)) < 0? r : r+1;
     }
 
-
-    /**
-     * Remove insignificant trailing zeros from this
-     * {@code BigDecimal} until the preferred scale is reached or no
-     * more zeros can be removed.  If the preferred scale is less than
-     * Integer.MIN_VALUE, all the trailing zeros will be removed.
-     *
-     * {@code BigInteger} assistance could help, here?
-     *
-     * <p>WARNING: This method should only be called on new objects as
-     * it mutates the value fields.
-     *
-     * @return this {@code BigDecimal} with a scale possibly reduced
-     * to be closed to the preferred scale.
-     */
-    private BigDecimal stripZerosToMatchScale(long preferredScale) {
-        this.inflate();
-        BigInteger qr[];                // quotient-remainder pair
-        while ( intVal.compareMagnitude(BigInteger.TEN) >= 0 &&
-                scale > preferredScale) {
-            if (intVal.testBit(0))
-                break;                  // odd number cannot end in 0
-            qr = intVal.divideAndRemainder(BigInteger.TEN);
-            if (qr[1].signum() != 0)
-                break;                  // non-0 remainder
-            intVal=qr[0];
-            scale = checkScale((long)scale-1);  // could Overflow
-            if (precision > 0)          // adjust precision if known
-              precision--;
-        }
-        if (intVal != null)
-            intCompact = compactValFor(intVal);
-        return this;
-    }
-
     /**
      * Check a scale for Underflow or Overflow.  If this BigDecimal is
      * nonzero, throw an exception if the scale is outof range. If this
@@ -3693,74 +3846,7 @@
         return asInt;
     }
 
-    /**
-     * Round an operand; used only if digits &gt; 0.  Does not change
-     * {@code this}; if rounding is needed a new {@code BigDecimal}
-     * is created and returned.
-     *
-     * @param mc the context to use.
-     * @throws ArithmeticException if the result is inexact but the
-     *         rounding mode is {@code UNNECESSARY}.
-     */
-    private BigDecimal roundOp(MathContext mc) {
-        BigDecimal rounded = doRound(this, mc);
-        return rounded;
-    }
-
-    /** Round this BigDecimal according to the MathContext settings;
-     *  used only if precision {@literal >} 0.
-     *
-     * <p>WARNING: This method should only be called on new objects as
-     * it mutates the value fields.
-     *
-     * @param mc the context to use.
-     * @throws ArithmeticException if the rounding mode is
-     *         {@code RoundingMode.UNNECESSARY} and the
-     *         {@code BigDecimal} operation would require rounding.
-     */
-    private void roundThis(MathContext mc) {
-        BigDecimal rounded = doRound(this, mc);
-        if (rounded == this)                 // wasn't rounded
-            return;
-        this.intVal     = rounded.intVal;
-        this.intCompact = rounded.intCompact;
-        this.scale      = rounded.scale;
-        this.precision  = rounded.precision;
-    }
-
-    /**
-     * Returns a {@code BigDecimal} rounded according to the
-     * MathContext settings; used only if {@code mc.precision > 0}.
-     * Does not change {@code this}; if rounding is needed a new
-     * {@code BigDecimal} is created and returned.
-     *
-     * @param mc the context to use.
-     * @return a {@code BigDecimal} rounded according to the MathContext
-     *         settings.  May return this, if no rounding needed.
-     * @throws ArithmeticException if the rounding mode is
-     *         {@code RoundingMode.UNNECESSARY} and the
-     *         result is inexact.
-     */
-    private static BigDecimal doRound(BigDecimal d, MathContext mc) {
-        int mcp = mc.precision;
-        int drop;
-        // This might (rarely) iterate to cover the 999=>1000 case
-        while ((drop = d.precision() - mcp) > 0) {
-            int newScale = d.checkScale((long)d.scale - drop);
-            int mode = mc.roundingMode.oldMode;
-            if (drop < LONG_TEN_POWERS_TABLE.length)
-                d = divideAndRound(d.intCompact, d.intVal,
-                                   LONG_TEN_POWERS_TABLE[drop], null,
-                                   newScale, mode, newScale);
-            else
-                d = divideAndRound(d.intCompact, d.intVal,
-                                   INFLATED, bigTenToThe(drop),
-                                   newScale, mode, newScale);
-        }
-        return d;
-    }
-
-    /**
+   /**
      * Returns the compact value for given {@code BigInteger}, or
      * INFLATED if too big. Relies on internal representation of
      * {@code BigInteger}.
@@ -3852,4 +3938,1290 @@
         }
         return this;
     }
+
+    /* the same as checkScale where value!=0 */
+    private static int checkScaleNonZero(long val) {
+        int asInt = (int)val;
+        if (asInt != val) {
+            throw new ArithmeticException(asInt>0 ? "Underflow":"Overflow");
+        }
+        return asInt;
+    }
+
+    private static int checkScale(long intCompact, long val) {
+        int asInt = (int)val;
+        if (asInt != val) {
+            asInt = val>Integer.MAX_VALUE ? Integer.MAX_VALUE : Integer.MIN_VALUE;
+            if (intCompact != 0)
+                throw new ArithmeticException(asInt>0 ? "Underflow":"Overflow");
+        }
+        return asInt;
+    }
+
+    private static int checkScale(BigInteger intVal, long val) {
+        int asInt = (int)val;
+        if (asInt != val) {
+            asInt = val>Integer.MAX_VALUE ? Integer.MAX_VALUE : Integer.MIN_VALUE;
+            if (intVal.signum() != 0)
+                throw new ArithmeticException(asInt>0 ? "Underflow":"Overflow");
+        }
+        return asInt;
+    }
+
+    /**
+     * Returns a {@code BigDecimal} rounded according to the MathContext
+     * settings;
+     * If rounding is needed a new {@code BigDecimal} is created and returned.
+     *
+     * @param val the value to be rounded
+     * @param mc the context to use.
+     * @return a {@code BigDecimal} rounded according to the MathContext
+     *         settings.  May return {@code value}, if no rounding needed.
+     * @throws ArithmeticException if the rounding mode is
+     *         {@code RoundingMode.UNNECESSARY} and the
+     *         result is inexact.
+     */
+    private static BigDecimal doRound(BigDecimal val, MathContext mc) {
+        int mcp = mc.precision;
+        boolean wasDivided = false;
+        if (mcp > 0) {
+            BigInteger intVal = val.intVal;
+            long compactVal = val.intCompact;
+            int scale = val.scale;
+            int prec = val.precision();
+            int mode = mc.roundingMode.oldMode;
+            int drop;
+            if (compactVal == INFLATED) {
+                drop = prec - mcp;
+                while (drop > 0) {
+                    scale = checkScaleNonZero((long) scale - drop);
+                    intVal = divideAndRoundByTenPow(intVal, drop, mode);
+                    wasDivided = true;
+                    compactVal = compactValFor(intVal);
+                    if (compactVal != INFLATED) {
+                        prec = longDigitLength(compactVal);
+                        break;
+                    }
+                    prec = bigDigitLength(intVal);
+                    drop = prec - mcp;
+                }
+            }
+            if (compactVal != INFLATED) {
+                drop = prec - mcp;  // drop can't be more than 18
+                while (drop > 0) {
+                    scale = checkScaleNonZero((long) scale - drop);
+                    compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
+                    wasDivided = true;
+                    prec = longDigitLength(compactVal);
+                    drop = prec - mcp;
+                    intVal = null;
+                }
+            }
+            return wasDivided ? new BigDecimal(intVal,compactVal,scale,prec) : val;
+        }
+        return val;
+    }
+
+    /*
+     * Returns a {@code BigDecimal} created from {@code long} value with
+     * given scale rounded according to the MathContext settings
+     */
+    private static BigDecimal doRound(long compactVal, int scale, MathContext mc) {
+        int mcp = mc.precision;
+        if (mcp > 0 && mcp < 19) {
+            int prec = longDigitLength(compactVal);
+            int drop = prec - mcp;  // drop can't be more than 18
+            while (drop > 0) {
+                scale = checkScaleNonZero((long) scale - drop);
+                compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
+                prec = longDigitLength(compactVal);
+                drop = prec - mcp;
+            }
+            return valueOf(compactVal, scale, prec);
+        }
+        return valueOf(compactVal, scale);
+    }
+
+    /*
+     * Returns a {@code BigDecimal} created from {@code BigInteger} value with
+     * given scale rounded according to the MathContext settings
+     */
+    private static BigDecimal doRound(BigInteger intVal, int scale, MathContext mc) {
+        int mcp = mc.precision;
+        int prec = 0;
+        if (mcp > 0) {
+            long compactVal = compactValFor(intVal);
+            int mode = mc.roundingMode.oldMode;
+            int drop;
+            if (compactVal == INFLATED) {
+                prec = bigDigitLength(intVal);
+                drop = prec - mcp;
+                while (drop > 0) {
+                    scale = checkScaleNonZero((long) scale - drop);
+                    intVal = divideAndRoundByTenPow(intVal, drop, mode);
+                    compactVal = compactValFor(intVal);
+                    if (compactVal != INFLATED) {
+                        break;
+                    }
+                    prec = bigDigitLength(intVal);
+                    drop = prec - mcp;
+                }
+            }
+            if (compactVal != INFLATED) {
+                prec = longDigitLength(compactVal);
+                drop = prec - mcp;     // drop can't be more than 18
+                while (drop > 0) {
+                    scale = checkScaleNonZero((long) scale - drop);
+                    compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
+                    prec = longDigitLength(compactVal);
+                    drop = prec - mcp;
+                }
+                return valueOf(compactVal,scale,prec);
+            }
+        }
+        return new BigDecimal(intVal,INFLATED,scale,prec);
+    }
+
+    /*
+     * Divides {@code BigInteger} value by ten power.
+     */
+    private static BigInteger divideAndRoundByTenPow(BigInteger intVal, int tenPow, int roundingMode) {
+        if (tenPow < LONG_TEN_POWERS_TABLE.length)
+            intVal = divideAndRound(intVal, LONG_TEN_POWERS_TABLE[tenPow], roundingMode);
+        else
+            intVal = divideAndRound(intVal, bigTenToThe(tenPow), roundingMode);
+        return intVal;
+    }
+
+    /**
+     * Internally used for division operation for division {@code long} by
+     * {@code long}.
+     * The returned {@code BigDecimal} object is the quotient whose scale is set
+     * to the passed in scale. If the remainder is not zero, it will be rounded
+     * based on the passed in roundingMode. Also, if the remainder is zero and
+     * the last parameter, i.e. preferredScale is NOT equal to scale, the
+     * trailing zeros of the result is stripped to match the preferredScale.
+     */
+    private static BigDecimal divideAndRound(long ldividend, long ldivisor, int scale, int roundingMode,
+                                             int preferredScale) {
+
+        int qsign; // quotient sign
+        long q = ldividend / ldivisor; // store quotient in long
+        if (roundingMode == ROUND_DOWN && scale == preferredScale)
+            return valueOf(q, scale);
+        long r = ldividend % ldivisor; // store remainder in long
+        qsign = ((ldividend < 0) == (ldivisor < 0)) ? 1 : -1;
+        if (r != 0) {
+            boolean increment = needIncrement(ldivisor, roundingMode, qsign, q, r);
+            return valueOf((increment ? q + qsign : q), scale);
+        } else {
+            if (preferredScale != scale)
+                return createAndStripZerosToMatchScale(q, scale, preferredScale);
+            else
+                return valueOf(q, scale);
+        }
+    }
+
+    /**
+     * Divides {@code long} by {@code long} and do rounding based on the
+     * passed in roundingMode.
+     */
+    private static long divideAndRound(long ldividend, long ldivisor, int roundingMode) {
+        int qsign; // quotient sign
+        long q = ldividend / ldivisor; // store quotient in long
+        if (roundingMode == ROUND_DOWN)
+            return q;
+        long r = ldividend % ldivisor; // store remainder in long
+        qsign = ((ldividend < 0) == (ldivisor < 0)) ? 1 : -1;
+        if (r != 0) {
+            boolean increment = needIncrement(ldivisor, roundingMode, qsign, q,     r);
+            return increment ? q + qsign : q;
+        } else {
+            return q;
+        }
+    }
+
+    /**
+     * Shared logic of need increment computation.
+     */
+    private static boolean commonNeedIncrement(int roundingMode, int qsign,
+                                        int cmpFracHalf, boolean oddQuot) {
+        switch(roundingMode) {
+        case ROUND_UNNECESSARY:
+            throw new ArithmeticException("Rounding necessary");
+
+        case ROUND_UP: // Away from zero
+            return true;
+
+        case ROUND_DOWN: // Towards zero
+            return false;
+
+        case ROUND_CEILING: // Towards +infinity
+            return qsign > 0;
+
+        case ROUND_FLOOR: // Towards -infinity
+            return qsign < 0;
+
+        default: // Some kind of half-way rounding
+            assert roundingMode >= ROUND_HALF_UP &&
+                roundingMode <= ROUND_HALF_EVEN: "Unexpected rounding mode" + RoundingMode.valueOf(roundingMode);
+
+            if (cmpFracHalf < 0 ) // We're closer to higher digit
+                return false;
+            else if (cmpFracHalf > 0 ) // We're closer to lower digit
+                return true;
+            else { // half-way
+                assert cmpFracHalf == 0;
+
+                switch(roundingMode) {
+                case ROUND_HALF_DOWN:
+                    return false;
+
+                case ROUND_HALF_UP:
+                    return true;
+
+                case ROUND_HALF_EVEN:
+                    return oddQuot;
+
+                default:
+                    throw new AssertionError("Unexpected rounding mode" + roundingMode);
+                }
+            }
+        }
+    }
+
+    /**
+     * Tests if quotient has to be incremented according the roundingMode
+     */
+    private static boolean needIncrement(long ldivisor, int roundingMode,
+                                         int qsign, long q, long r) {
+        assert r != 0L;
+
+        int cmpFracHalf;
+        if (r <= HALF_LONG_MIN_VALUE || r > HALF_LONG_MAX_VALUE) {
+            cmpFracHalf = 1; // 2 * r can't fit into long
+        } else {
+            cmpFracHalf = longCompareMagnitude(2 * r, ldivisor);
+        }
+
+        return commonNeedIncrement(roundingMode, qsign, cmpFracHalf, (q & 1L) != 0L);
+    }
+
+    /**
+     * Divides {@code BigInteger} value by {@code long} value and
+     * do rounding based on the passed in roundingMode.
+     */
+    private static BigInteger divideAndRound(BigInteger bdividend, long ldivisor, int roundingMode) {
+        boolean isRemainderZero; // record remainder is zero or not
+        int qsign; // quotient sign
+        long r = 0; // store quotient & remainder in long
+        MutableBigInteger mq = null; // store quotient
+        // Descend into mutables for faster remainder checks
+        MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag);
+        mq = new MutableBigInteger();
+        r = mdividend.divide(ldivisor, mq);
+        isRemainderZero = (r == 0);
+        qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
+        if (!isRemainderZero) {
+            if(needIncrement(ldivisor, roundingMode, qsign, mq, r)) {
+                mq.add(MutableBigInteger.ONE);
+            }
+        }
+        return mq.toBigInteger(qsign);
+    }
+
+    /**
+     * Internally used for division operation for division {@code BigInteger}
+     * by {@code long}.
+     * The returned {@code BigDecimal} object is the quotient whose scale is set
+     * to the passed in scale. If the remainder is not zero, it will be rounded
+     * based on the passed in roundingMode. Also, if the remainder is zero and
+     * the last parameter, i.e. preferredScale is NOT equal to scale, the
+     * trailing zeros of the result is stripped to match the preferredScale.
+     */
+    private static BigDecimal divideAndRound(BigInteger bdividend,
+                                             long ldivisor, int scale, int roundingMode, int preferredScale) {
+        boolean isRemainderZero; // record remainder is zero or not
+        int qsign; // quotient sign
+        long r = 0; // store quotient & remainder in long
+        MutableBigInteger mq = null; // store quotient
+        // Descend into mutables for faster remainder checks
+        MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag);
+        mq = new MutableBigInteger();
+        r = mdividend.divide(ldivisor, mq);
+        isRemainderZero = (r == 0);
+        qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
+        if (!isRemainderZero) {
+            if(needIncrement(ldivisor, roundingMode, qsign, mq, r)) {
+                mq.add(MutableBigInteger.ONE);
+            }
+            return mq.toBigDecimal(qsign, scale);
+        } else {
+            if (preferredScale != scale) {
+                long compactVal = mq.toCompactValue(qsign);
+                if(compactVal!=INFLATED) {
+                    return createAndStripZerosToMatchScale(compactVal, scale, preferredScale);
+                }
+                BigInteger intVal =  mq.toBigInteger(qsign);
+                return createAndStripZerosToMatchScale(intVal,scale, preferredScale);
+            } else {
+                return mq.toBigDecimal(qsign, scale);
+            }
+        }
+    }
+
+    /**
+     * Tests if quotient has to be incremented according the roundingMode
+     */
+    private static boolean needIncrement(long ldivisor, int roundingMode,
+                                         int qsign, MutableBigInteger mq, long r) {
+        assert r != 0L;
+
+        int cmpFracHalf;
+        if (r <= HALF_LONG_MIN_VALUE || r > HALF_LONG_MAX_VALUE) {
+            cmpFracHalf = 1; // 2 * r can't fit into long
+        } else {
+            cmpFracHalf = longCompareMagnitude(2 * r, ldivisor);
+        }
+
+        return commonNeedIncrement(roundingMode, qsign, cmpFracHalf, mq.isOdd());
+    }
+
+    /**
+     * Divides {@code BigInteger} value by {@code BigInteger} value and
+     * do rounding based on the passed in roundingMode.
+     */
+    private static BigInteger divideAndRound(BigInteger bdividend, BigInteger bdivisor, int roundingMode) {
+        boolean isRemainderZero; // record remainder is zero or not
+        int qsign; // quotient sign
+        // Descend into mutables for faster remainder checks
+        MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag);
+        MutableBigInteger mq = new MutableBigInteger();
+        MutableBigInteger mdivisor = new MutableBigInteger(bdivisor.mag);
+        MutableBigInteger mr = mdividend.divide(mdivisor, mq);
+        isRemainderZero = mr.isZero();
+        qsign = (bdividend.signum != bdivisor.signum) ? -1 : 1;
+        if (!isRemainderZero) {
+            if (needIncrement(mdivisor, roundingMode, qsign, mq, mr)) {
+                mq.add(MutableBigInteger.ONE);
+            }
+        }
+        return mq.toBigInteger(qsign);
+    }
+
+    /**
+     * Internally used for division operation for division {@code BigInteger}
+     * by {@code BigInteger}.
+     * The returned {@code BigDecimal} object is the quotient whose scale is set
+     * to the passed in scale. If the remainder is not zero, it will be rounded
+     * based on the passed in roundingMode. Also, if the remainder is zero and
+     * the last parameter, i.e. preferredScale is NOT equal to scale, the
+     * trailing zeros of the result is stripped to match the preferredScale.
+     */
+    private static BigDecimal divideAndRound(BigInteger bdividend, BigInteger bdivisor, int scale, int roundingMode,
+                                             int preferredScale) {
+        boolean isRemainderZero; // record remainder is zero or not
+        int qsign; // quotient sign
+        // Descend into mutables for faster remainder checks
+        MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag);
+        MutableBigInteger mq = new MutableBigInteger();
+        MutableBigInteger mdivisor = new MutableBigInteger(bdivisor.mag);
+        MutableBigInteger mr = mdividend.divide(mdivisor, mq);
+        isRemainderZero = mr.isZero();
+        qsign = (bdividend.signum != bdivisor.signum) ? -1 : 1;
+        if (!isRemainderZero) {
+            if (needIncrement(mdivisor, roundingMode, qsign, mq, mr)) {
+                mq.add(MutableBigInteger.ONE);
+            }
+            return mq.toBigDecimal(qsign, scale);
+        } else {
+            if (preferredScale != scale) {
+                long compactVal = mq.toCompactValue(qsign);
+                if (compactVal != INFLATED) {
+                    return createAndStripZerosToMatchScale(compactVal, scale, preferredScale);
+                }
+                BigInteger intVal = mq.toBigInteger(qsign);
+                return createAndStripZerosToMatchScale(intVal, scale, preferredScale);
+            } else {
+                return mq.toBigDecimal(qsign, scale);
+            }
+        }
+    }
+
+    /**
+     * Tests if quotient has to be incremented according the roundingMode
+     */
+    private static boolean needIncrement(MutableBigInteger mdivisor, int roundingMode,
+                                         int qsign, MutableBigInteger mq, MutableBigInteger mr) {
+        assert !mr.isZero();
+        int cmpFracHalf = mr.compareHalf(mdivisor);
+        return commonNeedIncrement(roundingMode, qsign, cmpFracHalf, mq.isOdd());
+    }
+
+    /**
+     * Remove insignificant trailing zeros from this
+     * {@code BigInteger} value until the preferred scale is reached or no
+     * more zeros can be removed.  If the preferred scale is less than
+     * Integer.MIN_VALUE, all the trailing zeros will be removed.
+     *
+     * @return new {@code BigDecimal} with a scale possibly reduced
+     * to be closed to the preferred scale.
+     */
+    private static BigDecimal createAndStripZerosToMatchScale(BigInteger intVal, int scale, long preferredScale) {
+        BigInteger qr[]; // quotient-remainder pair
+        while (intVal.compareMagnitude(BigInteger.TEN) >= 0
+               && scale > preferredScale) {
+            if (intVal.testBit(0))
+                break; // odd number cannot end in 0
+            qr = intVal.divideAndRemainder(BigInteger.TEN);
+            if (qr[1].signum() != 0)
+                break; // non-0 remainder
+            intVal = qr[0];
+            scale = checkScale(intVal,(long) scale - 1); // could Overflow
+        }
+        return valueOf(intVal, scale, 0);
+    }
+
+    /**
+     * Remove insignificant trailing zeros from this
+     * {@code long} value until the preferred scale is reached or no
+     * more zeros can be removed.  If the preferred scale is less than
+     * Integer.MIN_VALUE, all the trailing zeros will be removed.
+     *
+     * @return new {@code BigDecimal} with a scale possibly reduced
+     * to be closed to the preferred scale.
+     */
+    private static BigDecimal createAndStripZerosToMatchScale(long compactVal, int scale, long preferredScale) {
+        while (Math.abs(compactVal) >= 10L && scale > preferredScale) {
+            if ((compactVal & 1L) != 0L)
+                break; // odd number cannot end in 0
+            long r = compactVal % 10L;
+            if (r != 0L)
+                break; // non-0 remainder
+            compactVal /= 10;
+            scale = checkScale(compactVal, (long) scale - 1); // could Overflow
+        }
+        return valueOf(compactVal, scale);
+    }
+
+    private static BigDecimal stripZerosToMatchScale(BigInteger intVal, long intCompact, int scale, int preferredScale) {
+        if(intCompact!=INFLATED) {
+            return createAndStripZerosToMatchScale(intCompact, scale, preferredScale);
+        } else {
+            return createAndStripZerosToMatchScale(intVal==null ? INFLATED_BIGINT : intVal,
+                                                   scale, preferredScale);
+        }
+    }
+
+    /*
+     * returns INFLATED if oveflow
+     */
+    private static long add(long xs, long ys){
+        long sum = xs + ys;
+        // See "Hacker's Delight" section 2-12 for explanation of
+        // the overflow test.
+        if ( (((sum ^ xs) & (sum ^ ys))) >= 0L) { // not overflowed
+            return sum;
+        }
+        return INFLATED;
+    }
+
+    private static BigDecimal add(long xs, long ys, int scale){
+        long sum = add(xs, ys);
+        if (sum!=INFLATED)
+            return BigDecimal.valueOf(sum, scale);
+        return new BigDecimal(BigInteger.valueOf(xs).add(ys), scale);
+    }
+
+    private static BigDecimal add(final long xs, int scale1, final long ys, int scale2) {
+        long sdiff = (long) scale1 - scale2;
+        if (sdiff == 0) {
+            return add(xs, ys, scale1);
+        } else if (sdiff < 0) {
+            int raise = checkScale(xs,-sdiff);
+            long scaledX = longMultiplyPowerTen(xs, raise);
+            if (scaledX != INFLATED) {
+                return add(scaledX, ys, scale2);
+            } else {
+                BigInteger bigsum = bigMultiplyPowerTen(xs,raise).add(ys);
+                return ((xs^ys)>=0) ? // same sign test
+                    new BigDecimal(bigsum, INFLATED, scale2, 0)
+                    : valueOf(bigsum, scale2, 0);
+            }
+        } else {
+            int raise = checkScale(ys,sdiff);
+            long scaledY = longMultiplyPowerTen(ys, raise);
+            if (scaledY != INFLATED) {
+                return add(xs, scaledY, scale1);
+            } else {
+                BigInteger bigsum = bigMultiplyPowerTen(ys,raise).add(xs);
+                return ((xs^ys)>=0) ?
+                    new BigDecimal(bigsum, INFLATED, scale1, 0)
+                    : valueOf(bigsum, scale1, 0);
+            }
+        }
+    }
+
+    private static BigDecimal add(final long xs, int scale1, BigInteger snd, int scale2) {
+        int rscale = scale1;
+        long sdiff = (long)rscale - scale2;
+        boolean sameSigns =  (Long.signum(xs) == snd.signum);
+        BigInteger sum;
+        if (sdiff < 0) {
+            int raise = checkScale(xs,-sdiff);
+            rscale = scale2;
+            long scaledX = longMultiplyPowerTen(xs, raise);
+            if (scaledX == INFLATED) {
+                sum = snd.add(bigMultiplyPowerTen(xs,raise));
+            } else {
+                sum = snd.add(scaledX);
+            }
+        } else { //if (sdiff > 0) {
+            int raise = checkScale(snd,sdiff);
+            snd = bigMultiplyPowerTen(snd,raise);
+            sum = snd.add(xs);
+        }
+        return (sameSigns) ?
+            new BigDecimal(sum, INFLATED, rscale, 0) :
+            valueOf(sum, rscale, 0);
+    }
+
+    private static BigDecimal add(BigInteger fst, int scale1, BigInteger snd, int scale2) {
+        int rscale = scale1;
+        long sdiff = (long)rscale - scale2;
+        if (sdiff != 0) {
+            if (sdiff < 0) {
+                int raise = checkScale(fst,-sdiff);
+                rscale = scale2;
+                fst = bigMultiplyPowerTen(fst,raise);
+            } else {
+                int raise = checkScale(snd,sdiff);
+                snd = bigMultiplyPowerTen(snd,raise);
+            }
+        }
+        BigInteger sum = fst.add(snd);
+        return (fst.signum == snd.signum) ?
+                new BigDecimal(sum, INFLATED, rscale, 0) :
+                valueOf(sum, rscale, 0);
+    }
+
+    private static BigInteger bigMultiplyPowerTen(long value, int n) {
+        if (n <= 0)
+            return BigInteger.valueOf(value);
+        return bigTenToThe(n).multiply(value);
+    }
+
+    private static BigInteger bigMultiplyPowerTen(BigInteger value, int n) {
+        if (n <= 0)
+            return value;
+        if(n<LONG_TEN_POWERS_TABLE.length) {
+                return value.multiply(LONG_TEN_POWERS_TABLE[n]);
+        }
+        return value.multiply(bigTenToThe(n));
+    }
+
+    /**
+     * Returns a {@code BigDecimal} whose value is {@code (xs /
+     * ys)}, with rounding according to the context settings.
+     *
+     * Fast path - used only when (xscale <= yscale && yscale < 18
+     *  && mc.presision<18) {
+     */
+    private static BigDecimal divideSmallFastPath(final long xs, int xscale,
+                                                  final long ys, int yscale,
+                                                  long preferredScale, MathContext mc) {
+        int mcp = mc.precision;
+        int roundingMode = mc.roundingMode.oldMode;
+
+        assert (xscale <= yscale) && (yscale < 18) && (mcp < 18);
+        int xraise = yscale - xscale; // xraise >=0
+        long scaledX = (xraise==0) ? xs :
+            longMultiplyPowerTen(xs, xraise); // can't overflow here!
+        BigDecimal quotient;
+
+        int cmp = longCompareMagnitude(scaledX, ys);
+        if(cmp > 0) { // satisfy constraint (b)
+            yscale -= 1; // [that is, divisor *= 10]
+            int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp);
+            if (checkScaleNonZero((long) mcp + yscale) > xscale) {
+                // assert newScale >= xscale
+                int raise = checkScaleNonZero((long) mcp + yscale - xscale);
+                long scaledXs;
+                if ((scaledXs = longMultiplyPowerTen(xs, raise)) == INFLATED) {
+                    quotient = null;
+                    if((mcp-1) >=0 && (mcp-1)<LONG_TEN_POWERS_TABLE.length) {
+                        quotient = multiplyDivideAndRound(LONG_TEN_POWERS_TABLE[mcp-1], scaledX, ys, scl, roundingMode, checkScaleNonZero(preferredScale));
+                    }
+                    if(quotient==null) {
+                        BigInteger rb = bigMultiplyPowerTen(scaledX,mcp-1);
+                        quotient = divideAndRound(rb, ys,
+                                                  scl, roundingMode, checkScaleNonZero(preferredScale));
+                    }
+                } else {
+                    quotient = divideAndRound(scaledXs, ys, scl, roundingMode, checkScaleNonZero(preferredScale));
+                }
+            } else {
+                int newScale = checkScaleNonZero((long) xscale - mcp);
+                // assert newScale >= yscale
+                if (newScale == yscale) { // easy case
+                    quotient = divideAndRound(xs, ys, scl, roundingMode,checkScaleNonZero(preferredScale));
+                } else {
+                    int raise = checkScaleNonZero((long) newScale - yscale);
+                    long scaledYs;
+                    if ((scaledYs = longMultiplyPowerTen(ys, raise)) == INFLATED) {
+                        BigInteger rb = bigMultiplyPowerTen(ys,raise);
+                        quotient = divideAndRound(BigInteger.valueOf(xs),
+                                                  rb, scl, roundingMode,checkScaleNonZero(preferredScale));
+                    } else {
+                        quotient = divideAndRound(xs, scaledYs, scl, roundingMode,checkScaleNonZero(preferredScale));
+                    }
+                }
+            }
+        } else {
+            // abs(scaledX) <= abs(ys)
+            // result is "scaledX * 10^msp / ys"
+            int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp);
+            if(cmp==0) {
+                // abs(scaleX)== abs(ys) => result will be scaled 10^mcp + correct sign
+                quotient = roundedTenPower(((scaledX < 0) == (ys < 0)) ? 1 : -1, mcp, scl, checkScaleNonZero(preferredScale));
+            } else {
+                // abs(scaledX) < abs(ys)
+                long scaledXs;
+                if ((scaledXs = longMultiplyPowerTen(scaledX, mcp)) == INFLATED) {
+                    quotient = null;
+                    if(mcp<LONG_TEN_POWERS_TABLE.length) {
+                        quotient = multiplyDivideAndRound(LONG_TEN_POWERS_TABLE[mcp], scaledX, ys, scl, roundingMode, checkScaleNonZero(preferredScale));
+                    }
+                    if(quotient==null) {
+                        BigInteger rb = bigMultiplyPowerTen(scaledX,mcp);
+                        quotient = divideAndRound(rb, ys,
+                                                  scl, roundingMode, checkScaleNonZero(preferredScale));
+                    }
+                } else {
+                    quotient = divideAndRound(scaledXs, ys, scl, roundingMode, checkScaleNonZero(preferredScale));
+                }
+            }
+        }
+        // doRound, here, only affects 1000000000 case.
+        return doRound(quotient,mc);
+    }
+
+    /**
+     * Returns a {@code BigDecimal} whose value is {@code (xs /
+     * ys)}, with rounding according to the context settings.
+     */
+    private static BigDecimal divide(final long xs, int xscale, final long ys, int yscale, long preferredScale, MathContext mc) {
+        int mcp = mc.precision;
+        if(xscale <= yscale && yscale < 18 && mcp<18) {
+            return divideSmallFastPath(xs, xscale, ys, yscale, preferredScale, mc);
+        }
+        if (compareMagnitudeNormalized(xs, xscale, ys, yscale) > 0) {// satisfy constraint (b)
+            yscale -= 1; // [that is, divisor *= 10]
+        }
+        int roundingMode = mc.roundingMode.oldMode;
+        // In order to find out whether the divide generates the exact result,
+        // we avoid calling the above divide method. 'quotient' holds the
+        // return BigDecimal object whose scale will be set to 'scl'.
+        int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp);
+        BigDecimal quotient;
+        if (checkScaleNonZero((long) mcp + yscale) > xscale) {
+            int raise = checkScaleNonZero((long) mcp + yscale - xscale);
+            long scaledXs;
+            if ((scaledXs = longMultiplyPowerTen(xs, raise)) == INFLATED) {
+                BigInteger rb = bigMultiplyPowerTen(xs,raise);
+                quotient = divideAndRound(rb, ys, scl, roundingMode, checkScaleNonZero(preferredScale));
+            } else {
+                quotient = divideAndRound(scaledXs, ys, scl, roundingMode, checkScaleNonZero(preferredScale));
+            }
+        } else {
+            int newScale = checkScaleNonZero((long) xscale - mcp);
+            // assert newScale >= yscale
+            if (newScale == yscale) { // easy case
+                quotient = divideAndRound(xs, ys, scl, roundingMode,checkScaleNonZero(preferredScale));
+            } else {
+                int raise = checkScaleNonZero((long) newScale - yscale);
+                long scaledYs;
+                if ((scaledYs = longMultiplyPowerTen(ys, raise)) == INFLATED) {
+                    BigInteger rb = bigMultiplyPowerTen(ys,raise);
+                    quotient = divideAndRound(BigInteger.valueOf(xs),
+                                              rb, scl, roundingMode,checkScaleNonZero(preferredScale));
+                } else {
+                    quotient = divideAndRound(xs, scaledYs, scl, roundingMode,checkScaleNonZero(preferredScale));
+                }
+            }
+        }
+        // doRound, here, only affects 1000000000 case.
+        return doRound(quotient,mc);
+    }
+
+    /**
+     * Returns a {@code BigDecimal} whose value is {@code (xs /
+     * ys)}, with rounding according to the context settings.
+     */
+    private static BigDecimal divide(BigInteger xs, int xscale, long ys, int yscale, long preferredScale, MathContext mc) {
+        // Normalize dividend & divisor so that both fall into [0.1, 0.999...]
+        if ((-compareMagnitudeNormalized(ys, yscale, xs, xscale)) > 0) {// satisfy constraint (b)
+            yscale -= 1; // [that is, divisor *= 10]
+        }
+        int mcp = mc.precision;
+        int roundingMode = mc.roundingMode.oldMode;
+
+        // In order to find out whether the divide generates the exact result,
+        // we avoid calling the above divide method. 'quotient' holds the
+        // return BigDecimal object whose scale will be set to 'scl'.
+        BigDecimal quotient;
+        int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp);
+        if (checkScaleNonZero((long) mcp + yscale) > xscale) {
+            int raise = checkScaleNonZero((long) mcp + yscale - xscale);
+            BigInteger rb = bigMultiplyPowerTen(xs,raise);
+            quotient = divideAndRound(rb, ys, scl, roundingMode, checkScaleNonZero(preferredScale));
+        } else {
+            int newScale = checkScaleNonZero((long) xscale - mcp);
+            // assert newScale >= yscale
+            if (newScale == yscale) { // easy case
+                quotient = divideAndRound(xs, ys, scl, roundingMode,checkScaleNonZero(preferredScale));
+            } else {
+                int raise = checkScaleNonZero((long) newScale - yscale);
+                long scaledYs;
+                if ((scaledYs = longMultiplyPowerTen(ys, raise)) == INFLATED) {
+                    BigInteger rb = bigMultiplyPowerTen(ys,raise);
+                    quotient = divideAndRound(xs, rb, scl, roundingMode,checkScaleNonZero(preferredScale));
+                } else {
+                    quotient = divideAndRound(xs, scaledYs, scl, roundingMode,checkScaleNonZero(preferredScale));
+                }
+            }
+        }
+        // doRound, here, only affects 1000000000 case.
+        return doRound(quotient, mc);
+    }
+
+    /**
+     * Returns a {@code BigDecimal} whose value is {@code (xs /
+     * ys)}, with rounding according to the context settings.
+     */
+    private static BigDecimal divide(long xs, int xscale, BigInteger ys, int yscale, long preferredScale, MathContext mc) {
+        // Normalize dividend & divisor so that both fall into [0.1, 0.999...]
+        if (compareMagnitudeNormalized(xs, xscale, ys, yscale) > 0) {// satisfy constraint (b)
+            yscale -= 1; // [that is, divisor *= 10]
+        }
+        int mcp = mc.precision;
+        int roundingMode = mc.roundingMode.oldMode;
+
+        // In order to find out whether the divide generates the exact result,
+        // we avoid calling the above divide method. 'quotient' holds the
+        // return BigDecimal object whose scale will be set to 'scl'.
+        BigDecimal quotient;
+        int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp);
+        if (checkScaleNonZero((long) mcp + yscale) > xscale) {
+            int raise = checkScaleNonZero((long) mcp + yscale - xscale);
+            BigInteger rb = bigMultiplyPowerTen(xs,raise);
+            quotient = divideAndRound(rb, ys, scl, roundingMode, checkScaleNonZero(preferredScale));
+        } else {
+            int newScale = checkScaleNonZero((long) xscale - mcp);
+            int raise = checkScaleNonZero((long) newScale - yscale);
+            BigInteger rb = bigMultiplyPowerTen(ys,raise);
+            quotient = divideAndRound(BigInteger.valueOf(xs), rb, scl, roundingMode,checkScaleNonZero(preferredScale));
+        }
+        // doRound, here, only affects 1000000000 case.
+        return doRound(quotient, mc);
+    }
+
+    /**
+     * Returns a {@code BigDecimal} whose value is {@code (xs /
+     * ys)}, with rounding according to the context settings.
+     */
+    private static BigDecimal divide(BigInteger xs, int xscale, BigInteger ys, int yscale, long preferredScale, MathContext mc) {
+        // Normalize dividend & divisor so that both fall into [0.1, 0.999...]
+        if (compareMagnitudeNormalized(xs, xscale, ys, yscale) > 0) {// satisfy constraint (b)
+            yscale -= 1; // [that is, divisor *= 10]
+        }
+        int mcp = mc.precision;
+        int roundingMode = mc.roundingMode.oldMode;
+
+        // In order to find out whether the divide generates the exact result,
+        // we avoid calling the above divide method. 'quotient' holds the
+        // return BigDecimal object whose scale will be set to 'scl'.
+        BigDecimal quotient;
+        int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp);
+        if (checkScaleNonZero((long) mcp + yscale) > xscale) {
+            int raise = checkScaleNonZero((long) mcp + yscale - xscale);
+            BigInteger rb = bigMultiplyPowerTen(xs,raise);
+            quotient = divideAndRound(rb, ys, scl, roundingMode, checkScaleNonZero(preferredScale));
+        } else {
+            int newScale = checkScaleNonZero((long) xscale - mcp);
+            int raise = checkScaleNonZero((long) newScale - yscale);
+            BigInteger rb = bigMultiplyPowerTen(ys,raise);
+            quotient = divideAndRound(xs, rb, scl, roundingMode,checkScaleNonZero(preferredScale));
+        }
+        // doRound, here, only affects 1000000000 case.
+        return doRound(quotient, mc);
+    }
+
+    /*
+     * performs divideAndRound for (dividend0*dividend1, divisor)
+     * returns null if quotient can't fit into long value;
+     */
+    private static BigDecimal multiplyDivideAndRound(long dividend0, long dividend1, long divisor, int scale, int roundingMode,
+                                                     int preferredScale) {
+        int qsign = Long.signum(dividend0)*Long.signum(dividend1)*Long.signum(divisor);
+        dividend0 = Math.abs(dividend0);
+        dividend1 = Math.abs(dividend1);
+        divisor = Math.abs(divisor);
+        // multiply dividend0 * dividend1
+        long d0_hi = dividend0 >>> 32;
+        long d0_lo = dividend0 & LONG_MASK;
+        long d1_hi = dividend1 >>> 32;
+        long d1_lo = dividend1 & LONG_MASK;
+        long product = d0_lo * d1_lo;
+        long d0 = product & LONG_MASK;
+        long d1 = product >>> 32;
+        product = d0_hi * d1_lo + d1;
+        d1 = product & LONG_MASK;
+        long d2 = product >>> 32;
+        product = d0_lo * d1_hi + d1;
+        d1 = product & LONG_MASK;
+        d2 += product >>> 32;
+        long d3 = d2>>>32;
+        d2 &= LONG_MASK;
+        product = d0_hi*d1_hi + d2;
+        d2 = product & LONG_MASK;
+        d3 = ((product>>>32) + d3) & LONG_MASK;
+        final long dividendHi = make64(d3,d2);
+        final long dividendLo = make64(d1,d0);
+        // divide
+        return divideAndRound128(dividendHi, dividendLo, divisor, qsign, scale, roundingMode, preferredScale);
+    }
+
+    private static final long DIV_NUM_BASE = (1L<<32); // Number base (32 bits).
+
+    /*
+     * divideAndRound 128-bit value by long divisor.
+     * returns null if quotient can't fit into long value;
+     * Specialized version of Knuth's division
+     */
+    private static BigDecimal divideAndRound128(final long dividendHi, final long dividendLo, long divisor, int sign,
+                                                int scale, int roundingMode, int preferredScale) {
+        if (dividendHi >= divisor) {
+            return null;
+        }
+        final int shift = Long.numberOfLeadingZeros(divisor);
+        divisor <<= shift;
+
+        final long v1 = divisor >>> 32;
+        final long v0 = divisor & LONG_MASK;
+
+        long q1, q0;
+        long r_tmp;
+
+        long tmp = dividendLo << shift;
+        long u1 = tmp >>> 32;
+        long u0 = tmp & LONG_MASK;
+
+        tmp = (dividendHi << shift) | (dividendLo >>> 64 - shift);
+        long u2 = tmp & LONG_MASK;
+        tmp = divWord(tmp,v1);
+        q1 = tmp & LONG_MASK;
+        r_tmp = tmp >>> 32;
+        while(q1 >= DIV_NUM_BASE || unsignedLongCompare(q1*v0, make64(r_tmp, u1))) {
+            q1--;
+            r_tmp += v1;
+            if (r_tmp >= DIV_NUM_BASE)
+                break;
+        }
+        tmp = mulsub(u2,u1,v1,v0,q1);
+        u1 = tmp & LONG_MASK;
+        tmp = divWord(tmp,v1);
+        q0 = tmp & LONG_MASK;
+        r_tmp = tmp >>> 32;
+        while(q0 >= DIV_NUM_BASE || unsignedLongCompare(q0*v0,make64(r_tmp,u0))) {
+            q0--;
+            r_tmp += v1;
+            if (r_tmp >= DIV_NUM_BASE)
+                break;
+        }
+        if((int)q1 < 0) {
+            // result (which is positive and unsigned here)
+            // can't fit into long due to sign bit is used for value
+            MutableBigInteger mq = new MutableBigInteger(new int[]{(int)q1, (int)q0});
+            if (roundingMode == ROUND_DOWN && scale == preferredScale) {
+                return mq.toBigDecimal(sign, scale);
+            }
+            long r = mulsub(u1, u0, v1, v0, q0) >>> shift;
+            if (r != 0) {
+                if(needIncrement(divisor >>> shift, roundingMode, sign, mq, r)){
+                    mq.add(MutableBigInteger.ONE);
+                }
+                return mq.toBigDecimal(sign, scale);
+            } else {
+                if (preferredScale != scale) {
+                    BigInteger intVal =  mq.toBigInteger(sign);
+                    return createAndStripZerosToMatchScale(intVal,scale, preferredScale);
+                } else {
+                    return mq.toBigDecimal(sign, scale);
+                }
+            }
+        }
+        long q = make64(q1,q0);
+        q*=sign;
+        if (roundingMode == ROUND_DOWN && scale == preferredScale)
+            return valueOf(q, scale);
+        long r = mulsub(u1, u0, v1, v0, q0) >>> shift;
+        if (r != 0) {
+            boolean increment = needIncrement(divisor >>> shift, roundingMode, sign, q, r);
+            return valueOf((increment ? q + sign : q), scale);
+        } else {
+            if (preferredScale != scale) {
+                return createAndStripZerosToMatchScale(q, scale, preferredScale);
+            } else {
+                return valueOf(q, scale);
+            }
+        }
+    }
+
+    /*
+     * calculate divideAndRound for ldividend*10^raise / divisor
+     * when abs(dividend)==abs(divisor);
+     */
+    private static BigDecimal roundedTenPower(int qsign, int raise, int scale, int preferredScale) {
+        if (scale > preferredScale) {
+            int diff = scale - preferredScale;
+            if(diff < raise) {
+                return scaledTenPow(raise - diff, qsign, preferredScale);
+            } else {
+                return valueOf(qsign,scale-raise);
+            }
+        } else {
+            return scaledTenPow(raise, qsign, scale);
+        }
+    }
+
+    static BigDecimal scaledTenPow(int n, int sign, int scale) {
+        if (n < LONG_TEN_POWERS_TABLE.length)
+            return valueOf(sign*LONG_TEN_POWERS_TABLE[n],scale);
+        else {
+            BigInteger unscaledVal = bigTenToThe(n);
+            if(sign==-1) {
+                unscaledVal = unscaledVal.negate();
+            }
+            return new BigDecimal(unscaledVal, INFLATED, scale, n+1);
+        }
+    }
+
+    private static long divWord(long n, long dLong) {
+        long r;
+        long q;
+        if (dLong == 1) {
+            q = (int)n;
+            return (q & LONG_MASK);
+        }
+        // Approximate the quotient and remainder
+        q = (n >>> 1) / (dLong >>> 1);
+        r = n - q*dLong;
+
+        // Correct the approximation
+        while (r < 0) {
+            r += dLong;
+            q--;
+        }
+        while (r >= dLong) {
+            r -= dLong;
+            q++;
+        }
+        // n - q*dlong == r && 0 <= r <dLong, hence we're done.
+        return (r << 32) | (q & LONG_MASK);
+    }
+
+    private static long make64(long hi, long lo) {
+        return hi<<32 | lo;
+    }
+
+    private static long mulsub(long u1, long u0, final long v1, final long v0, long q0) {
+        long tmp = u0 - q0*v0;
+        return make64(u1 + (tmp>>>32) - q0*v1,tmp & LONG_MASK);
+    }
+
+    private static boolean unsignedLongCompare(long one, long two) {
+        return (one+Long.MIN_VALUE) > (two+Long.MIN_VALUE);
+    }
+
+    private static boolean unsignedLongCompareEq(long one, long two) {
+        return (one+Long.MIN_VALUE) >= (two+Long.MIN_VALUE);
+    }
+
+
+    // Compare Normalize dividend & divisor so that both fall into [0.1, 0.999...]
+    private static int compareMagnitudeNormalized(long xs, int xscale, long ys, int yscale) {
+        // assert xs!=0 && ys!=0
+        int sdiff = xscale - yscale;
+        if (sdiff != 0) {
+            if (sdiff < 0) {
+                xs = longMultiplyPowerTen(xs, -sdiff);
+            } else { // sdiff > 0
+                ys = longMultiplyPowerTen(ys, sdiff);
+            }
+        }
+        if (xs != INFLATED)
+            return (ys != INFLATED) ? longCompareMagnitude(xs, ys) : -1;
+        else
+            return 1;
+    }
+
+    // Compare Normalize dividend & divisor so that both fall into [0.1, 0.999...]
+    private static int compareMagnitudeNormalized(long xs, int xscale, BigInteger ys, int yscale) {
+        // assert "ys can't be represented as long"
+        if (xs == 0)
+            return -1;
+        int sdiff = xscale - yscale;
+        if (sdiff < 0) {
+            if (longMultiplyPowerTen(xs, -sdiff) == INFLATED ) {
+                return bigMultiplyPowerTen(xs, -sdiff).compareMagnitude(ys);
+            }
+        }
+        return -1;
+    }
+
+    // Compare Normalize dividend & divisor so that both fall into [0.1, 0.999...]
+    private static int compareMagnitudeNormalized(BigInteger xs, int xscale, BigInteger ys, int yscale) {
+        int sdiff = xscale - yscale;
+        if (sdiff < 0) {
+            return bigMultiplyPowerTen(xs, -sdiff).compareMagnitude(ys);
+        } else { // sdiff >= 0
+            return xs.compareMagnitude(bigMultiplyPowerTen(ys, sdiff));
+        }
+    }
+
+    private static long multiply(long x, long y){
+                long product = x * y;
+        long ax = Math.abs(x);
+        long ay = Math.abs(y);
+        if (((ax | ay) >>> 31 == 0) || (y == 0) || (product / y == x)){
+                        return product;
+                }
+        return INFLATED;
+    }
+
+    private static BigDecimal multiply(long x, long y, int scale) {
+        long product = multiply(x, y);
+        if(product!=INFLATED) {
+            return valueOf(product,scale);
+        }
+        return new BigDecimal(BigInteger.valueOf(x).multiply(y),INFLATED,scale,0);
+    }
+
+    private static BigDecimal multiply(long x, BigInteger y, int scale) {
+        if(x==0) {
+            return zeroValueOf(scale);
+        }
+        return new BigDecimal(y.multiply(x),INFLATED,scale,0);
+    }
+
+    private static BigDecimal multiply(BigInteger x, BigInteger y, int scale) {
+        return new BigDecimal(x.multiply(y),INFLATED,scale,0);
+    }
+
+    /**
+     * Multiplies two long values and rounds according {@code MathContext}
+     */
+    private static BigDecimal multiplyAndRound(long x, long y, int scale, MathContext mc) {
+        long product = multiply(x, y);
+        if(product!=INFLATED) {
+            return doRound(product, scale, mc);
+        }
+        // attempt to do it in 128 bits
+        int rsign = 1;
+        if(x < 0) {
+            x = -x;
+            rsign = -1;
+        }
+        if(y < 0) {
+            y = -y;
+            rsign *= -1;
+        }
+        // multiply dividend0 * dividend1
+        long m0_hi = x >>> 32;
+        long m0_lo = x & LONG_MASK;
+        long m1_hi = y >>> 32;
+        long m1_lo = y & LONG_MASK;
+        product = m0_lo * m1_lo;
+        long m0 = product & LONG_MASK;
+        long m1 = product >>> 32;
+        product = m0_hi * m1_lo + m1;
+        m1 = product & LONG_MASK;
+        long m2 = product >>> 32;
+        product = m0_lo * m1_hi + m1;
+        m1 = product & LONG_MASK;
+        m2 += product >>> 32;
+        long m3 = m2>>>32;
+        m2 &= LONG_MASK;
+        product = m0_hi*m1_hi + m2;
+        m2 = product & LONG_MASK;
+        m3 = ((product>>>32) + m3) & LONG_MASK;
+        final long mHi = make64(m3,m2);
+        final long mLo = make64(m1,m0);
+        BigDecimal res = doRound128(mHi, mLo, rsign, scale, mc);
+        if(res!=null) {
+            return res;
+        }
+        res = new BigDecimal(BigInteger.valueOf(x).multiply(y*rsign), INFLATED, scale, 0);
+        return doRound(res,mc);
+    }
+
+    private static BigDecimal multiplyAndRound(long x, BigInteger y, int scale, MathContext mc) {
+        if(x==0) {
+            return zeroValueOf(scale);
+        }
+        return doRound(y.multiply(x), scale, mc);
+    }
+
+    private static BigDecimal multiplyAndRound(BigInteger x, BigInteger y, int scale, MathContext mc) {
+        return doRound(x.multiply(y), scale, mc);
+    }
+
+    /**
+     * rounds 128-bit value according {@code MathContext}
+     * returns null if result can't be repsented as compact BigDecimal.
+     */
+    private static BigDecimal doRound128(long hi, long lo, int sign, int scale, MathContext mc) {
+        int mcp = mc.precision;
+        int drop;
+        BigDecimal res = null;
+        if(((drop = precision(hi, lo) - mcp) > 0)&&(drop<LONG_TEN_POWERS_TABLE.length)) {
+            scale = checkScaleNonZero((long)scale - drop);
+            res = divideAndRound128(hi, lo, LONG_TEN_POWERS_TABLE[drop], sign, scale, mc.roundingMode.oldMode, scale);
+        }
+        if(res!=null) {
+            return doRound(res,mc);
+        }
+        return null;
+    }
+
+    private static final long[][] LONGLONG_TEN_POWERS_TABLE = {
+        {   0L, 0x8AC7230489E80000L },  //10^19
+        {       0x5L, 0x6bc75e2d63100000L },  //10^20
+        {       0x36L, 0x35c9adc5dea00000L },  //10^21
+        {       0x21eL, 0x19e0c9bab2400000L  },  //10^22
+        {       0x152dL, 0x02c7e14af6800000L  },  //10^23
+        {       0xd3c2L, 0x1bcecceda1000000L  },  //10^24
+        {       0x84595L, 0x161401484a000000L  },  //10^25
+        {       0x52b7d2L, 0xdcc80cd2e4000000L  },  //10^26
+        {       0x33b2e3cL, 0x9fd0803ce8000000L  },  //10^27
+        {       0x204fce5eL, 0x3e25026110000000L  },  //10^28
+        {       0x1431e0faeL, 0x6d7217caa0000000L  },  //10^29
+        {       0xc9f2c9cd0L, 0x4674edea40000000L  },  //10^30
+        {       0x7e37be2022L, 0xc0914b2680000000L  },  //10^31
+        {       0x4ee2d6d415bL, 0x85acef8100000000L  },  //10^32
+        {       0x314dc6448d93L, 0x38c15b0a00000000L  },  //10^33
+        {       0x1ed09bead87c0L, 0x378d8e6400000000L  },  //10^34
+        {       0x13426172c74d82L, 0x2b878fe800000000L  },  //10^35
+        {       0xc097ce7bc90715L, 0xb34b9f1000000000L  },  //10^36
+        {       0x785ee10d5da46d9L, 0x00f436a000000000L  },  //10^37
+        {       0x4b3b4ca85a86c47aL, 0x098a224000000000L  },  //10^38
+    };
+
+    /*
+     * returns precision of 128-bit value
+     */
+    private static int precision(long hi, long lo){
+        if(hi==0) {
+            if(lo>=0) {
+                return longDigitLength(lo);
+            }
+            return (unsignedLongCompareEq(lo, LONGLONG_TEN_POWERS_TABLE[0][1])) ? 20 : 19;
+            // 0x8AC7230489E80000L  = unsigned 2^19
+        }
+        int r = ((128 - Long.numberOfLeadingZeros(hi) + 1) * 1233) >>> 12;
+        int idx = r-19;
+        return (idx >= LONGLONG_TEN_POWERS_TABLE.length || longLongCompareMagnitude(hi, lo,
+                                                                                    LONGLONG_TEN_POWERS_TABLE[idx][0], LONGLONG_TEN_POWERS_TABLE[idx][1])) ? r : r + 1;
+    }
+
+    /*
+     * returns true if 128 bit number <hi0,lo0> is less then <hi1,lo1>
+     * hi0 & hi1 should be non-negative
+     */
+    private static boolean longLongCompareMagnitude(long hi0, long lo0, long hi1, long lo1) {
+        if(hi0!=hi1) {
+            return hi0<hi1;
+        }
+        return (lo0+Long.MIN_VALUE) <(lo1+Long.MIN_VALUE);
+    }
+
+    private static BigDecimal divide(long dividend, int dividendScale, long divisor, int divisorScale, int scale, int roundingMode) {
+        if (checkScale(dividend,(long)scale + divisorScale) > dividendScale) {
+            int newScale = scale + divisorScale;
+            int raise = newScale - dividendScale;
+            if(raise<LONG_TEN_POWERS_TABLE.length) {
+                long xs = dividend;
+                if ((xs = longMultiplyPowerTen(xs, raise)) != INFLATED) {
+                    return divideAndRound(xs, divisor, scale, roundingMode, scale);
+                }
+                BigDecimal q = multiplyDivideAndRound(LONG_TEN_POWERS_TABLE[raise], dividend, divisor, scale, roundingMode, scale);
+                if(q!=null) {
+                    return q;
+                }
+            }
+            BigInteger scaledDividend = bigMultiplyPowerTen(dividend, raise);
+            return divideAndRound(scaledDividend, divisor, scale, roundingMode, scale);
+        } else {
+            int newScale = checkScale(divisor,(long)dividendScale - scale);
+            int raise = newScale - divisorScale;
+            if(raise<LONG_TEN_POWERS_TABLE.length) {
+                long ys = divisor;
+                if ((ys = longMultiplyPowerTen(ys, raise)) != INFLATED) {
+                    return divideAndRound(dividend, ys, scale, roundingMode, scale);
+                }
+            }
+            BigInteger scaledDivisor = bigMultiplyPowerTen(divisor, raise);
+            return divideAndRound(BigInteger.valueOf(dividend), scaledDivisor, scale, roundingMode, scale);
+        }
+    }
+
+    private static BigDecimal divide(BigInteger dividend, int dividendScale, long divisor, int divisorScale, int scale, int roundingMode) {
+        if (checkScale(dividend,(long)scale + divisorScale) > dividendScale) {
+            int newScale = scale + divisorScale;
+            int raise = newScale - dividendScale;
+            BigInteger scaledDividend = bigMultiplyPowerTen(dividend, raise);
+            return divideAndRound(scaledDividend, divisor, scale, roundingMode, scale);
+        } else {
+            int newScale = checkScale(divisor,(long)dividendScale - scale);
+            int raise = newScale - divisorScale;
+            if(raise<LONG_TEN_POWERS_TABLE.length) {
+                long ys = divisor;
+                if ((ys = longMultiplyPowerTen(ys, raise)) != INFLATED) {
+                    return divideAndRound(dividend, ys, scale, roundingMode, scale);
+                }
+            }
+            BigInteger scaledDivisor = bigMultiplyPowerTen(divisor, raise);
+            return divideAndRound(dividend, scaledDivisor, scale, roundingMode, scale);
+        }
+    }
+
+    private static BigDecimal divide(long dividend, int dividendScale, BigInteger divisor, int divisorScale, int scale, int roundingMode) {
+        if (checkScale(dividend,(long)scale + divisorScale) > dividendScale) {
+            int newScale = scale + divisorScale;
+            int raise = newScale - dividendScale;
+            BigInteger scaledDividend = bigMultiplyPowerTen(dividend, raise);
+            return divideAndRound(scaledDividend, divisor, scale, roundingMode, scale);
+        } else {
+            int newScale = checkScale(divisor,(long)dividendScale - scale);
+            int raise = newScale - divisorScale;
+            BigInteger scaledDivisor = bigMultiplyPowerTen(divisor, raise);
+            return divideAndRound(BigInteger.valueOf(dividend), scaledDivisor, scale, roundingMode, scale);
+        }
+    }
+
+    private static BigDecimal divide(BigInteger dividend, int dividendScale, BigInteger divisor, int divisorScale, int scale, int roundingMode) {
+        if (checkScale(dividend,(long)scale + divisorScale) > dividendScale) {
+            int newScale = scale + divisorScale;
+            int raise = newScale - dividendScale;
+            BigInteger scaledDividend = bigMultiplyPowerTen(dividend, raise);
+            return divideAndRound(scaledDividend, divisor, scale, roundingMode, scale);
+        } else {
+            int newScale = checkScale(divisor,(long)dividendScale - scale);
+            int raise = newScale - divisorScale;
+            BigInteger scaledDivisor = bigMultiplyPowerTen(divisor, raise);
+            return divideAndRound(dividend, scaledDivisor, scale, roundingMode, scale);
+        }
+    }
+
 }
--- a/jdk/src/share/classes/java/math/BigInteger.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/math/BigInteger.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, 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,6 +31,7 @@
 
 import java.util.Random;
 import java.io.*;
+import java.util.Arrays;
 
 /**
  * Immutable arbitrary-precision integers.  All operations behave as if
@@ -353,27 +354,17 @@
         mag = trustedStripLeadingZeroInts(magnitude);
     }
 
-    // Constructs a new BigInteger using a char array with radix=10
-    BigInteger(char[] val) {
+    /*
+     * Constructs a new BigInteger using a char array with radix=10.
+     * Sign is precalculated outside and not allowed in the val.
+     */
+    BigInteger(char[] val, int sign, int len) {
         int cursor = 0, numDigits;
-        int len = val.length;
-
-        // Check for leading minus sign
-        int sign = 1;
-        if (val[0] == '-') {
-            if (len == 1)
-                throw new NumberFormatException("Zero length BigInteger");
-            sign = -1;
-            cursor = 1;
-        } else if (val[0] == '+') {
-            if (len == 1)
-                throw new NumberFormatException("Zero length BigInteger");
-            cursor = 1;
-        }
 
         // Skip leading zeros and compute number of digits in magnitude
-        while (cursor < len && Character.digit(val[cursor], 10) == 0)
+        while (cursor < len && Character.digit(val[cursor], 10) == 0) {
             cursor++;
+        }
         if (cursor == len) {
             signum = 0;
             mag = ZERO.mag;
@@ -382,7 +373,6 @@
 
         numDigits = len - cursor;
         signum = sign;
-
         // Pre-allocate array of expected size
         int numWords;
         if (len < 10) {
@@ -1058,6 +1048,73 @@
     }
 
     /**
+     * Package private methods used by BigDecimal code to add a BigInteger
+     * with a long. Assumes val is not equal to INFLATED.
+     */
+    BigInteger add(long val) {
+        if (val == 0)
+            return this;
+        if (signum == 0)
+            return valueOf(val);
+        if (Long.signum(val) == signum)
+            return new BigInteger(add(mag, Math.abs(val)), signum);
+        int cmp = compareMagnitude(val);
+        if (cmp == 0)
+            return ZERO;
+        int[] resultMag = (cmp > 0 ? subtract(mag, Math.abs(val)) : subtract(Math.abs(val), mag));
+        resultMag = trustedStripLeadingZeroInts(resultMag);
+        return new BigInteger(resultMag, cmp == signum ? 1 : -1);
+    }
+
+    /**
+     * Adds the contents of the int array x and long value val. This
+     * method allocates a new int array to hold the answer and returns
+     * a reference to that array.  Assumes x.length &gt; 0 and val is
+     * non-negative
+     */
+    private static int[] add(int[] x, long val) {
+        int[] y;
+        long sum = 0;
+        int xIndex = x.length;
+        int[] result;
+        int highWord = (int)(val >>> 32);
+        if (highWord==0) {
+            result = new int[xIndex];
+            sum = (x[--xIndex] & LONG_MASK) + val;
+            result[xIndex] = (int)sum;
+        } else {
+            if (xIndex == 1) {
+                result = new int[2];
+                sum = val  + (x[0] & LONG_MASK);
+                result[1] = (int)sum;
+                result[0] = (int)(sum >>> 32);
+                return result;
+            } else {
+                result = new int[xIndex];
+                sum = (x[--xIndex] & LONG_MASK) + (val & LONG_MASK);
+                result[xIndex] = (int)sum;
+                sum = (x[--xIndex] & LONG_MASK) + (highWord & LONG_MASK) + (sum >>> 32);
+                result[xIndex] = (int)sum;
+            }
+        }
+        // Copy remainder of longer number while carry propagation is required
+        boolean carry = (sum >>> 32 != 0);
+        while (xIndex > 0 && carry)
+            carry = ((result[--xIndex] = x[xIndex] + 1) == 0);
+        // Copy remainder of longer number
+        while (xIndex > 0)
+            result[--xIndex] = x[xIndex];
+        // Grow result if necessary
+        if (carry) {
+            int bigger[] = new int[result.length + 1];
+            System.arraycopy(result, 0, bigger, 1, result.length);
+            bigger[0] = 0x01;
+            return bigger;
+        }
+        return result;
+    }
+
+    /**
      * Adds the contents of the int arrays x and y. This method allocates
      * a new int array to hold the answer and returns a reference to that
      * array.
@@ -1074,14 +1131,17 @@
         int yIndex = y.length;
         int result[] = new int[xIndex];
         long sum = 0;
-
-        // Add common parts of both numbers
-        while(yIndex > 0) {
-            sum = (x[--xIndex] & LONG_MASK) +
-                  (y[--yIndex] & LONG_MASK) + (sum >>> 32);
+        if(yIndex==1) {
+            sum = (x[--xIndex] & LONG_MASK) + (y[0] & LONG_MASK) ;
             result[xIndex] = (int)sum;
+        } else {
+            // Add common parts of both numbers
+            while(yIndex > 0) {
+                sum = (x[--xIndex] & LONG_MASK) +
+                      (y[--yIndex] & LONG_MASK) + (sum >>> 32);
+                result[xIndex] = (int)sum;
+            }
         }
-
         // Copy remainder of longer number while carry propagation is required
         boolean carry = (sum >>> 32 != 0);
         while (xIndex > 0 && carry)
@@ -1101,6 +1161,71 @@
         return result;
     }
 
+    private static int[] subtract(long val, int[] little) {
+        int highWord = (int)(val >>> 32);
+        if (highWord==0) {
+            int result[] = new int[1];
+            result[0] = (int)(val - (little[0] & LONG_MASK));
+            return result;
+        } else {
+            int result[] = new int[2];
+            if(little.length==1) {
+                long difference = ((int)val & LONG_MASK) - (little[0] & LONG_MASK);
+                result[1] = (int)difference;
+                // Subtract remainder of longer number while borrow propagates
+                boolean borrow = (difference >> 32 != 0);
+                if(borrow) {
+                    result[0] = highWord - 1;
+                } else {        // Copy remainder of longer number
+                    result[0] = highWord;
+                }
+                return result;
+            } else { // little.length==2
+                long difference = ((int)val & LONG_MASK) - (little[1] & LONG_MASK);
+                result[1] = (int)difference;
+                difference = (highWord & LONG_MASK) - (little[0] & LONG_MASK) + (difference >> 32);
+                result[0] = (int)difference;
+                return result;
+            }
+        }
+    }
+
+    /**
+     * Subtracts the contents of the second argument (val) from the
+     * first (big).  The first int array (big) must represent a larger number
+     * than the second.  This method allocates the space necessary to hold the
+     * answer.
+     * assumes val &gt;= 0
+     */
+    private static int[] subtract(int[] big, long val) {
+        int highWord = (int)(val >>> 32);
+        int bigIndex = big.length;
+        int result[] = new int[bigIndex];
+        long difference = 0;
+
+        if (highWord==0) {
+            difference = (big[--bigIndex] & LONG_MASK) - val;
+            result[bigIndex] = (int)difference;
+        } else {
+            difference = (big[--bigIndex] & LONG_MASK) - (val & LONG_MASK);
+            result[bigIndex] = (int)difference;
+            difference = (big[--bigIndex] & LONG_MASK) - (highWord & LONG_MASK) + (difference >> 32);
+            result[bigIndex] = (int)difference;
+        }
+
+
+        // Subtract remainder of longer number while borrow propagates
+        boolean borrow = (difference >> 32 != 0);
+        while (bigIndex > 0 && borrow)
+            borrow = ((result[--bigIndex] = big[bigIndex] - 1) == -1);
+
+        // Copy remainder of longer number
+        while (bigIndex > 0)
+            result[--bigIndex] = big[bigIndex];
+
+        return result;
+    }
+
     /**
      * Returns a BigInteger whose value is {@code (this - val)}.
      *
@@ -1165,11 +1290,39 @@
     public BigInteger multiply(BigInteger val) {
         if (val.signum == 0 || signum == 0)
             return ZERO;
-
+        int resultSign = signum == val.signum ? 1 : -1;
+        if (val.mag.length == 1) {
+            return  multiplyByInt(mag,val.mag[0], resultSign);
+        }
+        if(mag.length == 1) {
+            return multiplyByInt(val.mag,mag[0], resultSign);
+        }
         int[] result = multiplyToLen(mag, mag.length,
                                      val.mag, val.mag.length, null);
         result = trustedStripLeadingZeroInts(result);
-        return new BigInteger(result, signum == val.signum ? 1 : -1);
+        return new BigInteger(result, resultSign);
+    }
+
+    private static BigInteger multiplyByInt(int[] x, int y, int sign) {
+        if(Integer.bitCount(y)==1) {
+            return new BigInteger(shiftLeft(x,Integer.numberOfTrailingZeros(y)), sign);
+        }
+        int xlen = x.length;
+        int[] rmag =  new int[xlen + 1];
+        long carry = 0;
+        long yl = y & LONG_MASK;
+        int rstart = rmag.length - 1;
+        for (int i = xlen - 1; i >= 0; i--) {
+            long product = (x[i] & LONG_MASK) * yl + carry;
+            rmag[rstart--] = (int)product;
+            carry = product >>> 32;
+        }
+        if (carry == 0L) {
+            rmag = java.util.Arrays.copyOfRange(rmag, 1, rmag.length);
+        } else {
+            rmag[rstart] = (int)carry;
+        }
+        return new BigInteger(rmag, sign);
     }
 
     /**
@@ -1339,8 +1492,8 @@
                           a = new MutableBigInteger(this.mag),
                           b = new MutableBigInteger(val.mag);
 
-        a.divide(b, q);
-        return q.toBigInteger(this.signum == val.signum ? 1 : -1);
+        a.divide(b, q, false);
+        return q.toBigInteger(this.signum * val.signum);
     }
 
     /**
@@ -1460,14 +1613,12 @@
         } else { // Array must be resized
             if (nBits <= (32-bitsInHighWord)) {
                 int result[] = new int[nInts+len];
-                for (int i=0; i<len; i++)
-                    result[i] = a[i];
+                System.arraycopy(a, 0, result, 0, len);
                 primitiveLeftShift(result, result.length, nBits);
                 return result;
             } else {
                 int result[] = new int[nInts+len+1];
-                for (int i=0; i<len; i++)
-                    result[i] = a[i];
+                System.arraycopy(a, 0, result, 0, len);
                 primitiveRightShift(result, result.length, 32 - nBits);
                 return result;
             }
@@ -1755,9 +1906,7 @@
         b = montReduce(b, mod, modLen, inv);
 
         // Set t to high half of b
-        int[] t = new int[modLen];
-        for(int i=0; i<modLen; i++)
-            t[i] = b[i];
+        int[] t = Arrays.copyOf(b, modLen);
 
         // Fill in the table with odd powers of the base
         for (int i=1; i<tblmask; i++) {
@@ -1854,14 +2003,11 @@
 
         // Convert result out of Montgomery form and return
         int[] t2 = new int[2*modLen];
-        for(int i=0; i<modLen; i++)
-            t2[i+modLen] = b[i];
+        System.arraycopy(b, 0, t2, modLen, modLen);
 
         b = montReduce(t2, mod, modLen, inv);
 
-        t2 = new int[modLen];
-        for(int i=0; i<modLen; i++)
-            t2[i] = b[i];
+        t2 = Arrays.copyOf(b, modLen);
 
         return new BigInteger(1, t2);
     }
@@ -2002,8 +2148,7 @@
         // Copy remaining ints of mag
         int numInts = (p + 31) >>> 5;
         int[] mag = new int[numInts];
-        for (int i=0; i<numInts; i++)
-            mag[i] = this.mag[i + (this.mag.length - numInts)];
+        System.arraycopy(this.mag, (this.mag.length - numInts), mag, 0, numInts);
 
         // Mask out any excess bits
         int excessBits = (numInts << 5) - p;
@@ -2069,7 +2214,12 @@
                 return shiftRight(-n);
             }
         }
-
+        int[] newMag = shiftLeft(mag, n);
+
+        return new BigInteger(newMag, signum);
+    }
+
+    private static int[] shiftLeft(int[] mag, int n) {
         int nInts = n >>> 5;
         int nBits = n & 0x1f;
         int magLen = mag.length;
@@ -2077,8 +2227,7 @@
 
         if (nBits == 0) {
             newMag = new int[magLen + nInts];
-            for (int i=0; i<magLen; i++)
-                newMag[i] = mag[i];
+            System.arraycopy(mag, 0, newMag, 0, magLen);
         } else {
             int i = 0;
             int nBits2 = 32 - nBits;
@@ -2094,8 +2243,7 @@
                 newMag[i++] = mag[j++] << nBits | mag[j] >>> nBits2;
             newMag[i] = mag[j] << nBits;
         }
-
-        return new BigInteger(newMag, signum);
+        return newMag;
     }
 
     /**
@@ -2132,9 +2280,7 @@
 
         if (nBits == 0) {
             int newMagLen = magLen - nInts;
-            newMag = new int[newMagLen];
-            for (int i=0; i<newMagLen; i++)
-                newMag[i] = mag[i];
+            newMag = Arrays.copyOf(mag, newMagLen);
         } else {
             int i = 0;
             int highBits = mag[0] >>> nBits;
@@ -2405,7 +2551,7 @@
                  if (signum < 0) {
                      // Check if magnitude is a power of two
                      boolean pow2 = (Integer.bitCount(mag[0]) == 1);
-                     for(int i=1; i< len && pow2; i++)
+                     for (int i=1; i< len && pow2; i++)
                          pow2 = (mag[i] == 0);
 
                      n = (pow2 ? magBitLength -1 : magBitLength);
@@ -2530,6 +2676,49 @@
     }
 
     /**
+     * Version of compareMagnitude that compares magnitude with long value.
+     * val can't be Long.MIN_VALUE.
+     */
+    final int compareMagnitude(long val) {
+        assert val != Long.MIN_VALUE;
+        int[] m1 = mag;
+        int len = m1.length;
+        if(len > 2) {
+            return 1;
+        }
+        if (val < 0) {
+            val = -val;
+        }
+        int highWord = (int)(val >>> 32);
+        if (highWord==0) {
+            if (len < 1)
+                return -1;
+            if (len > 1)
+                return 1;
+            int a = m1[0];
+            int b = (int)val;
+            if (a != b) {
+                return ((a & LONG_MASK) < (b & LONG_MASK))? -1 : 1;
+            }
+            return 0;
+        } else {
+            if (len < 2)
+                return -1;
+            int a = m1[0];
+            int b = highWord;
+            if (a != b) {
+                return ((a & LONG_MASK) < (b & LONG_MASK))? -1 : 1;
+            }
+            a = m1[1];
+            b = (int)val;
+            if (a != b) {
+                return ((a & LONG_MASK) < (b & LONG_MASK))? -1 : 1;
+            }
+            return 0;
+        }
+    }
+
+    /**
      * Compares this BigInteger with the specified Object for equality.
      *
      * @param  x Object to which this BigInteger is to be compared.
@@ -3114,25 +3303,35 @@
         }
 
         // Commit final fields via Unsafe
-        unsafe.putIntVolatile(this, signumOffset, sign);
+        UnsafeHolder.putSign(this, sign);
 
         // Calculate mag field from magnitude and discard magnitude
-        unsafe.putObjectVolatile(this, magOffset,
-                                 stripLeadingZeroBytes(magnitude));
+        UnsafeHolder.putMag(this, stripLeadingZeroBytes(magnitude));
     }
 
     // Support for resetting final fields while deserializing
-    private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
-    private static final long signumOffset;
-    private static final long magOffset;
-    static {
-        try {
-            signumOffset = unsafe.objectFieldOffset
-                (BigInteger.class.getDeclaredField("signum"));
-            magOffset = unsafe.objectFieldOffset
-                (BigInteger.class.getDeclaredField("mag"));
-        } catch (Exception ex) {
-            throw new Error(ex);
+    private static class UnsafeHolder {
+        private static final sun.misc.Unsafe unsafe;
+        private static final long signumOffset;
+        private static final long magOffset;
+        static {
+            try {
+                unsafe = sun.misc.Unsafe.getUnsafe();
+                signumOffset = unsafe.objectFieldOffset
+                    (BigInteger.class.getDeclaredField("signum"));
+                magOffset = unsafe.objectFieldOffset
+                    (BigInteger.class.getDeclaredField("mag"));
+            } catch (Exception ex) {
+                throw new ExceptionInInitializerError(ex);
+            }
+        }
+
+        static void putSign(BigInteger bi, int sign) {
+            unsafe.putIntVolatile(bi, signumOffset, sign);
+        }
+
+        static void putMag(BigInteger bi, int[] magnitude) {
+            unsafe.putObjectVolatile(bi, magOffset, magnitude);
         }
     }
 
--- a/jdk/src/share/classes/java/math/MutableBigInteger.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/math/MutableBigInteger.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, 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
@@ -160,7 +160,7 @@
      */
     BigDecimal toBigDecimal(int sign, int scale) {
         if (intLen == 0 || sign == 0)
-            return BigDecimal.valueOf(0, scale);
+            return BigDecimal.zeroValueOf(scale);
         int[] mag = getMagnitudeArray();
         int len = mag.length;
         int d = mag[0];
@@ -171,7 +171,28 @@
         long v = (len == 2) ?
             ((mag[1] & LONG_MASK) | (d & LONG_MASK) << 32) :
             d & LONG_MASK;
-        return new BigDecimal(null, sign == -1 ? -v : v, scale, 0);
+        return BigDecimal.valueOf(sign == -1 ? -v : v, scale);
+    }
+
+    /**
+     * This is for internal use in converting from a MutableBigInteger
+     * object into a long value given a specified sign.
+     * returns INFLATED if value is not fit into long
+     */
+    long toCompactValue(int sign) {
+        if (intLen == 0 || sign == 0)
+            return 0L;
+        int[] mag = getMagnitudeArray();
+        int len = mag.length;
+        int d = mag[0];
+        // If this MutableBigInteger can not be fitted into long, we need to
+        // make a BigInteger object for the resultant BigDecimal object.
+        if (len > 2 || (d < 0 && len == 2))
+            return INFLATED;
+        long v = (len == 2) ?
+            ((mag[1] & LONG_MASK) | (d & LONG_MASK) << 32) :
+            d & LONG_MASK;
+        return sign == -1 ? -v : v;
     }
 
     /**
@@ -544,6 +565,24 @@
     }
 
     /**
+     * The method is the same as mulsun, except the fact that q array is not
+     * updated, the only result of the method is borrow flag.
+     */
+    private int mulsubBorrow(int[] q, int[] a, int x, int len, int offset) {
+        long xLong = x & LONG_MASK;
+        long carry = 0;
+        offset += len;
+        for (int j=len-1; j >= 0; j--) {
+            long product = (a[j] & LONG_MASK) * xLong + carry;
+            long difference = q[offset--] - product;
+            carry = (product >>> 32)
+                     + (((difference & LONG_MASK) >
+                         (((~(int)product) & LONG_MASK))) ? 1:0);
+        }
+        return (int)carry;
+    }
+
+    /**
      * Right shift this MutableBigInteger n bits, where n is
      * less than 32.
      * Assumes that intLen > 0, n > 0 for speed
@@ -842,20 +881,20 @@
             rem = (int) (remLong - (quotient.value[0] * divisorLong));
             remLong = rem & LONG_MASK;
         }
-
         int xlen = intLen;
-        int[] qWord = new int[2];
         while (--xlen > 0) {
-            long dividendEstimate = (remLong<<32) |
-                (value[offset + intLen - xlen] & LONG_MASK);
+            long dividendEstimate = (remLong << 32) |
+                    (value[offset + intLen - xlen] & LONG_MASK);
+            int q;
             if (dividendEstimate >= 0) {
-                qWord[0] = (int) (dividendEstimate / divisorLong);
-                qWord[1] = (int) (dividendEstimate - qWord[0] * divisorLong);
+                q = (int) (dividendEstimate / divisorLong);
+                rem = (int) (dividendEstimate - q * divisorLong);
             } else {
-                divWord(qWord, dividendEstimate, divisor);
+                long tmp = divWord(dividendEstimate, divisor);
+                q = (int) (tmp & LONG_MASK);
+                rem = (int) (tmp >>> 32);
             }
-            quotient.value[intLen - xlen] = qWord[0];
-            rem = qWord[1];
+            quotient.value[intLen - xlen] = q;
             remLong = rem & LONG_MASK;
         }
 
@@ -879,40 +918,45 @@
      *
      */
     MutableBigInteger divide(MutableBigInteger b, MutableBigInteger quotient) {
+        return divide(b,quotient,true);
+    }
+
+    MutableBigInteger divide(MutableBigInteger b, MutableBigInteger quotient, boolean needReminder) {
         if (b.intLen == 0)
             throw new ArithmeticException("BigInteger divide by zero");
 
         // Dividend is zero
         if (intLen == 0) {
             quotient.intLen = quotient.offset;
-            return new MutableBigInteger();
+            return needReminder ? new MutableBigInteger() : null;
         }
 
         int cmp = compare(b);
         // Dividend less than divisor
         if (cmp < 0) {
             quotient.intLen = quotient.offset = 0;
-            return new MutableBigInteger(this);
+            return needReminder ? new MutableBigInteger(this) : null;
         }
         // Dividend equal to divisor
         if (cmp == 0) {
             quotient.value[0] = quotient.intLen = 1;
             quotient.offset = 0;
-            return new MutableBigInteger();
+            return needReminder ? new MutableBigInteger() : null;
         }
 
         quotient.clear();
         // Special case one word divisor
         if (b.intLen == 1) {
             int r = divideOneWord(b.value[b.offset], quotient);
-            if (r == 0)
-                return new MutableBigInteger();
-            return new MutableBigInteger(r);
+            if(needReminder) {
+                if (r == 0)
+                    return new MutableBigInteger();
+                return new MutableBigInteger(r);
+            } else {
+                return null;
+            }
         }
-
-        // Copy divisor value to protect divisor
-        int[] div = Arrays.copyOfRange(b.value, b.offset, b.offset + b.intLen);
-        return divideMagnitude(div, quotient);
+        return divideMagnitude(b, quotient, needReminder);
     }
 
     /**
@@ -940,30 +984,72 @@
         if (d == 0)
             return divideOneWord((int)v, quotient) & LONG_MASK;
         else {
-            int[] div = new int[]{ d, (int)(v & LONG_MASK) };
-            return divideMagnitude(div, quotient).toLong();
+            return divideLongMagnitude(v, quotient).toLong();
         }
     }
 
+    private static void copyAndShift(int[] src, int srcFrom, int srcLen, int[] dst, int dstFrom, int shift) {
+        int n2 = 32 - shift;
+        int c=src[srcFrom];
+        for (int i=0; i < srcLen-1; i++) {
+            int b = c;
+            c = src[++srcFrom];
+            dst[dstFrom+i] = (b << shift) | (c >>> n2);
+        }
+        dst[dstFrom+srcLen-1] = c << shift;
+    }
+
     /**
-     * Divide this MutableBigInteger by the divisor represented by its magnitude
-     * array. The quotient will be placed into the provided quotient object &
+     * Divide this MutableBigInteger by the divisor.
+     * The quotient will be placed into the provided quotient object &
      * the remainder object is returned.
      */
-    private MutableBigInteger divideMagnitude(int[] divisor,
-                                              MutableBigInteger quotient) {
-
-        // Remainder starts as dividend with space for a leading zero
-        MutableBigInteger rem = new MutableBigInteger(new int[intLen + 1]);
-        System.arraycopy(value, offset, rem.value, 1, intLen);
-        rem.intLen = intLen;
-        rem.offset = 1;
+    private MutableBigInteger divideMagnitude(MutableBigInteger div,
+                                              MutableBigInteger quotient,
+                                              boolean needReminder ) {
+        // assert div.intLen > 1
+        // D1 normalize the divisor
+        int shift = Integer.numberOfLeadingZeros(div.value[div.offset]);
+        // Copy divisor value to protect divisor
+        final int dlen = div.intLen;
+        int[] divisor;
+        MutableBigInteger rem; // Remainder starts as dividend with space for a leading zero
+        if (shift > 0) {
+            divisor = new int[dlen];
+            copyAndShift(div.value,div.offset,dlen,divisor,0,shift);
+            if(Integer.numberOfLeadingZeros(value[offset])>=shift) {
+                int[] remarr = new int[intLen + 1];
+                rem = new MutableBigInteger(remarr);
+                rem.intLen = intLen;
+                rem.offset = 1;
+                copyAndShift(value,offset,intLen,remarr,1,shift);
+            } else {
+                int[] remarr = new int[intLen + 2];
+                rem = new MutableBigInteger(remarr);
+                rem.intLen = intLen+1;
+                rem.offset = 1;
+                int rFrom = offset;
+                int c=0;
+                int n2 = 32 - shift;
+                for (int i=1; i < intLen+1; i++,rFrom++) {
+                    int b = c;
+                    c = value[rFrom];
+                    remarr[i] = (b << shift) | (c >>> n2);
+                }
+                remarr[intLen+1] = c << shift;
+            }
+        } else {
+            divisor = Arrays.copyOfRange(div.value, div.offset, div.offset + div.intLen);
+            rem = new MutableBigInteger(new int[intLen + 1]);
+            System.arraycopy(value, offset, rem.value, 1, intLen);
+            rem.intLen = intLen;
+            rem.offset = 1;
+        }
 
         int nlen = rem.intLen;
 
         // Set the quotient size
-        int dlen = divisor.length;
-        int limit = nlen - dlen + 1;
+        final int limit = nlen - dlen + 1;
         if (quotient.value.length < limit) {
             quotient.value = new int[limit];
             quotient.offset = 0;
@@ -971,14 +1057,6 @@
         quotient.intLen = limit;
         int[] q = quotient.value;
 
-        // D1 normalize the divisor
-        int shift = Integer.numberOfLeadingZeros(divisor[0]);
-        if (shift > 0) {
-            // First shift will not grow array
-            BigInteger.primitiveLeftShift(divisor, dlen, shift);
-            // But this one might
-            rem.leftShift(shift);
-        }
 
         // Must insert leading 0 in rem if its length did not change
         if (rem.intLen == nlen) {
@@ -990,10 +1068,9 @@
         int dh = divisor[0];
         long dhLong = dh & LONG_MASK;
         int dl = divisor[1];
-        int[] qWord = new int[2];
 
         // D2 Initialize j
-        for(int j=0; j<limit; j++) {
+        for(int j=0; j<limit-1; j++) {
             // D3 Calculate qhat
             // estimate qhat
             int qhat = 0;
@@ -1013,9 +1090,9 @@
                     qhat = (int) (nChunk / dhLong);
                     qrem = (int) (nChunk - (qhat * dhLong));
                 } else {
-                    divWord(qWord, nChunk, dh);
-                    qhat = qWord[0];
-                    qrem = qWord[1];
+                    long tmp = divWord(nChunk, dh);
+                    qhat = (int) (tmp & LONG_MASK);
+                    qrem = (int) (tmp >>> 32);
                 }
             }
 
@@ -1053,6 +1130,181 @@
             // Store the quotient digit
             q[j] = qhat;
         } // D7 loop on j
+        // D3 Calculate qhat
+        // estimate qhat
+        int qhat = 0;
+        int qrem = 0;
+        boolean skipCorrection = false;
+        int nh = rem.value[limit - 1 + rem.offset];
+        int nh2 = nh + 0x80000000;
+        int nm = rem.value[limit + rem.offset];
+
+        if (nh == dh) {
+            qhat = ~0;
+            qrem = nh + nm;
+            skipCorrection = qrem + 0x80000000 < nh2;
+        } else {
+            long nChunk = (((long) nh) << 32) | (nm & LONG_MASK);
+            if (nChunk >= 0) {
+                qhat = (int) (nChunk / dhLong);
+                qrem = (int) (nChunk - (qhat * dhLong));
+            } else {
+                long tmp = divWord(nChunk, dh);
+                qhat = (int) (tmp & LONG_MASK);
+                qrem = (int) (tmp >>> 32);
+            }
+        }
+        if (qhat != 0) {
+            if (!skipCorrection) { // Correct qhat
+                long nl = rem.value[limit + 1 + rem.offset] & LONG_MASK;
+                long rs = ((qrem & LONG_MASK) << 32) | nl;
+                long estProduct = (dl & LONG_MASK) * (qhat & LONG_MASK);
+
+                if (unsignedLongCompare(estProduct, rs)) {
+                    qhat--;
+                    qrem = (int) ((qrem & LONG_MASK) + dhLong);
+                    if ((qrem & LONG_MASK) >= dhLong) {
+                        estProduct -= (dl & LONG_MASK);
+                        rs = ((qrem & LONG_MASK) << 32) | nl;
+                        if (unsignedLongCompare(estProduct, rs))
+                            qhat--;
+                    }
+                }
+            }
+
+
+            // D4 Multiply and subtract
+            int borrow;
+            rem.value[limit - 1 + rem.offset] = 0;
+            if(needReminder)
+                borrow = mulsub(rem.value, divisor, qhat, dlen, limit - 1 + rem.offset);
+            else
+                borrow = mulsubBorrow(rem.value, divisor, qhat, dlen, limit - 1 + rem.offset);
+
+            // D5 Test remainder
+            if (borrow + 0x80000000 > nh2) {
+                // D6 Add back
+                if(needReminder)
+                    divadd(divisor, rem.value, limit - 1 + 1 + rem.offset);
+                qhat--;
+            }
+
+            // Store the quotient digit
+            q[(limit - 1)] = qhat;
+        }
+
+
+        if(needReminder) {
+            // D8 Unnormalize
+            if (shift > 0)
+                rem.rightShift(shift);
+            rem.normalize();
+        }
+        quotient.normalize();
+        return needReminder ? rem : null;
+    }
+
+    /**
+     * Divide this MutableBigInteger by the divisor represented by positive long
+     * value. The quotient will be placed into the provided quotient object &
+     * the remainder object is returned.
+     */
+    private MutableBigInteger divideLongMagnitude(long ldivisor, MutableBigInteger quotient) {
+        // Remainder starts as dividend with space for a leading zero
+        MutableBigInteger rem = new MutableBigInteger(new int[intLen + 1]);
+        System.arraycopy(value, offset, rem.value, 1, intLen);
+        rem.intLen = intLen;
+        rem.offset = 1;
+
+        int nlen = rem.intLen;
+
+        int limit = nlen - 2 + 1;
+        if (quotient.value.length < limit) {
+            quotient.value = new int[limit];
+            quotient.offset = 0;
+        }
+        quotient.intLen = limit;
+        int[] q = quotient.value;
+
+        // D1 normalize the divisor
+        int shift = Long.numberOfLeadingZeros(ldivisor);
+        if (shift > 0) {
+            ldivisor<<=shift;
+            rem.leftShift(shift);
+        }
+
+        // Must insert leading 0 in rem if its length did not change
+        if (rem.intLen == nlen) {
+            rem.offset = 0;
+            rem.value[0] = 0;
+            rem.intLen++;
+        }
+
+        int dh = (int)(ldivisor >>> 32);
+        long dhLong = dh & LONG_MASK;
+        int dl = (int)(ldivisor & LONG_MASK);
+
+        // D2 Initialize j
+        for (int j = 0; j < limit; j++) {
+            // D3 Calculate qhat
+            // estimate qhat
+            int qhat = 0;
+            int qrem = 0;
+            boolean skipCorrection = false;
+            int nh = rem.value[j + rem.offset];
+            int nh2 = nh + 0x80000000;
+            int nm = rem.value[j + 1 + rem.offset];
+
+            if (nh == dh) {
+                qhat = ~0;
+                qrem = nh + nm;
+                skipCorrection = qrem + 0x80000000 < nh2;
+            } else {
+                long nChunk = (((long) nh) << 32) | (nm & LONG_MASK);
+                if (nChunk >= 0) {
+                    qhat = (int) (nChunk / dhLong);
+                    qrem = (int) (nChunk - (qhat * dhLong));
+                } else {
+                    long tmp = divWord(nChunk, dh);
+                    qhat =(int)(tmp & LONG_MASK);
+                    qrem = (int)(tmp>>>32);
+                }
+            }
+
+            if (qhat == 0)
+                continue;
+
+            if (!skipCorrection) { // Correct qhat
+                long nl = rem.value[j + 2 + rem.offset] & LONG_MASK;
+                long rs = ((qrem & LONG_MASK) << 32) | nl;
+                long estProduct = (dl & LONG_MASK) * (qhat & LONG_MASK);
+
+                if (unsignedLongCompare(estProduct, rs)) {
+                    qhat--;
+                    qrem = (int) ((qrem & LONG_MASK) + dhLong);
+                    if ((qrem & LONG_MASK) >= dhLong) {
+                        estProduct -= (dl & LONG_MASK);
+                        rs = ((qrem & LONG_MASK) << 32) | nl;
+                        if (unsignedLongCompare(estProduct, rs))
+                            qhat--;
+                    }
+                }
+            }
+
+            // D4 Multiply and subtract
+            rem.value[j + rem.offset] = 0;
+            int borrow = mulsubLong(rem.value, dh, dl, qhat,  j + rem.offset);
+
+            // D5 Test remainder
+            if (borrow + 0x80000000 > nh2) {
+                // D6 Add back
+                divaddLong(dh,dl, rem.value, j + 1 + rem.offset);
+                qhat--;
+            }
+
+            // Store the quotient digit
+            q[j] = qhat;
+        } // D7 loop on j
 
         // D8 Unnormalize
         if (shift > 0)
@@ -1064,6 +1316,46 @@
     }
 
     /**
+     * A primitive used for division by long.
+     * Specialized version of the method divadd.
+     * dh is a high part of the divisor, dl is a low part
+     */
+    private int divaddLong(int dh, int dl, int[] result, int offset) {
+        long carry = 0;
+
+        long sum = (dl & LONG_MASK) + (result[1+offset] & LONG_MASK);
+        result[1+offset] = (int)sum;
+
+        sum = (dh & LONG_MASK) + (result[offset] & LONG_MASK) + carry;
+        result[offset] = (int)sum;
+        carry = sum >>> 32;
+        return (int)carry;
+    }
+
+    /**
+     * This method is used for division by long.
+     * Specialized version of the method sulsub.
+     * dh is a high part of the divisor, dl is a low part
+     */
+    private int mulsubLong(int[] q, int dh, int dl, int x, int offset) {
+        long xLong = x & LONG_MASK;
+        offset += 2;
+        long product = (dl & LONG_MASK) * xLong;
+        long difference = q[offset] - product;
+        q[offset--] = (int)difference;
+        long carry = (product >>> 32)
+                 + (((difference & LONG_MASK) >
+                     (((~(int)product) & LONG_MASK))) ? 1:0);
+        product = (dh & LONG_MASK) * xLong + carry;
+        difference = q[offset] - product;
+        q[offset--] = (int)difference;
+        carry = (product >>> 32)
+                 + (((difference & LONG_MASK) >
+                     (((~(int)product) & LONG_MASK))) ? 1:0);
+        return (int)carry;
+    }
+
+    /**
      * Compare two longs as if they were unsigned.
      * Returns true iff one is bigger than two.
      */
@@ -1075,19 +1367,22 @@
      * This method divides a long quantity by an int to estimate
      * qhat for two multi precision numbers. It is used when
      * the signed value of n is less than zero.
+     * Returns long value where high 32 bits contain reminder value and
+     * low 32 bits contain quotient value.
      */
-    private void divWord(int[] result, long n, int d) {
+    static long divWord(long n, int d) {
         long dLong = d & LONG_MASK;
-
+        long r;
+        long q;
         if (dLong == 1) {
-            result[0] = (int)n;
-            result[1] = 0;
-            return;
+            q = (int)n;
+            r = 0;
+            return (r << 32) | (q & LONG_MASK);
         }
 
         // Approximate the quotient and remainder
-        long q = (n >>> 1) / (dLong >>> 1);
-        long r = n - q*dLong;
+        q = (n >>> 1) / (dLong >>> 1);
+        r = n - q*dLong;
 
         // Correct the approximation
         while (r < 0) {
@@ -1098,10 +1393,8 @@
             r -= dLong;
             q++;
         }
-
         // n - q*dlong == r && 0 <= r <dLong, hence we're done.
-        result[0] = (int)q;
-        result[1] = (int)r;
+        return (r << 32) | (q & LONG_MASK);
     }
 
     /**
@@ -1473,5 +1766,4 @@
         mod.subtract(t1);
         return mod;
     }
-
 }
--- a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java	Wed Jul 05 17:50:47 2017 +0200
@@ -457,10 +457,10 @@
         }
 
         /*
-         * If connection has been reset then return 0 to indicate
-         * there are no buffered bytes.
+         * If connection has been reset or shut down for input, then return 0
+         * to indicate there are no buffered bytes.
          */
-        if (isConnectionReset()) {
+        if (isConnectionReset() || shut_rd) {
             return 0;
         }
 
--- a/jdk/src/share/classes/java/net/DatagramSocket.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/net/DatagramSocket.java	Wed Jul 05 17:50:47 2017 +0200
@@ -174,9 +174,7 @@
      * @see SecurityManager#checkListen
      */
     public DatagramSocket() throws SocketException {
-        // create a datagram socket.
-        createImpl();
-        bind(new InetSocketAddress(0));
+        this(new InetSocketAddress(0));
     }
 
     /**
@@ -221,7 +219,12 @@
         // create a datagram socket.
         createImpl();
         if (bindaddr != null) {
-            bind(bindaddr);
+            try {
+                bind(bindaddr);
+            } finally {
+                if (!isBound())
+                    close();
+            }
         }
     }
 
--- a/jdk/src/share/classes/java/net/MulticastSocket.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/net/MulticastSocket.java	Wed Jul 05 17:50:47 2017 +0200
@@ -162,7 +162,12 @@
         setReuseAddress(true);
 
         if (bindaddr != null) {
-            bind(bindaddr);
+            try {
+                bind(bindaddr);
+            } finally {
+                if (!isBound())
+                    close();
+            }
         }
     }
 
--- a/jdk/src/share/classes/java/net/Socket.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/net/Socket.java	Wed Jul 05 17:50:47 2017 +0200
@@ -28,7 +28,6 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.IOException;
-import java.io.InterruptedIOException;
 import java.nio.channels.SocketChannel;
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
@@ -421,10 +420,13 @@
             createImpl(stream);
             if (localAddr != null)
                 bind(localAddr);
-            if (address != null)
-                connect(address);
-        } catch (IOException e) {
-            close();
+            connect(address);
+        } catch (IOException | IllegalArgumentException | SecurityException e) {
+            try {
+                close();
+            } catch (IOException ce) {
+                e.addSuppressed(ce);
+            }
             throw e;
         }
     }
@@ -1436,8 +1438,9 @@
      * Any data sent to the input stream side of the socket is acknowledged
      * and then silently discarded.
      * <p>
-     * If you read from a socket input stream after invoking
-     * shutdownInput() on the socket, the stream will return EOF.
+     * If you read from a socket input stream after invoking this method on the
+     * socket, the stream's {@code available} method will return 0, and its
+     * {@code read} methods will return {@code -1} (end of stream).
      *
      * @exception IOException if an I/O error occurs when shutting down this
      * socket.
--- a/jdk/src/share/classes/java/net/SocketImpl.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/net/SocketImpl.java	Wed Jul 05 17:50:47 2017 +0200
@@ -181,8 +181,9 @@
      * Any data sent to this socket is acknowledged and then
      * silently discarded.
      *
-     * If you read from a socket input stream after invoking
-     * shutdownInput() on the socket, the stream will return EOF.
+     * If you read from a socket input stream after invoking this method on the
+     * socket, the stream's {@code available} method will return 0, and its
+     * {@code read} methods will return {@code -1} (end of stream).
      *
      * @exception IOException if an I/O error occurs when shutting down this
      * socket.
--- a/jdk/src/share/classes/java/net/URI.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/net/URI.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1711,6 +1711,8 @@
                     i++;
                     continue;
                 }
+                if (d != '%')
+                    return false;
                 i++;
                 if (toLower(s.charAt(i)) != toLower(t.charAt(i)))
                     return false;
--- a/jdk/src/share/classes/java/rmi/dgc/VMID.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/rmi/dgc/VMID.java	Wed Jul 05 17:50:47 2017 +0200
@@ -170,7 +170,7 @@
             /* can't happen, but be deterministic anyway. */
             addrHash = new byte[0];
         } catch (NoSuchAlgorithmException complain) {
-            throw new InternalError(complain.toString());
+            throw new InternalError(complain.toString(), complain);
         }
         return addrHash;
     }
--- a/jdk/src/share/classes/java/security/cert/CollectionCertStoreParameters.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/security/cert/CollectionCertStoreParameters.java	Wed Jul 05 17:50:47 2017 +0200
@@ -122,7 +122,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             /* Cannot happen */
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 
--- a/jdk/src/share/classes/java/security/cert/LDAPCertStoreParameters.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/security/cert/LDAPCertStoreParameters.java	Wed Jul 05 17:50:47 2017 +0200
@@ -128,7 +128,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             /* Cannot happen */
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 
--- a/jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java	Wed Jul 05 17:50:47 2017 +0200
@@ -175,7 +175,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             /* Cannot happen */
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 }
--- a/jdk/src/share/classes/java/security/cert/PKIXCertPathValidatorResult.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/security/cert/PKIXCertPathValidatorResult.java	Wed Jul 05 17:50:47 2017 +0200
@@ -136,7 +136,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             /* Cannot happen */
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 
--- a/jdk/src/share/classes/java/security/cert/PKIXParameters.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/security/cert/PKIXParameters.java	Wed Jul 05 17:50:47 2017 +0200
@@ -683,7 +683,7 @@
             return copy;
         } catch (CloneNotSupportedException e) {
             /* Cannot happen */
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 
--- a/jdk/src/share/classes/java/security/cert/X509CRLSelector.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/security/cert/X509CRLSelector.java	Wed Jul 05 17:50:47 2017 +0200
@@ -708,7 +708,7 @@
             return copy;
         } catch (CloneNotSupportedException e) {
             /* Cannot happen */
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 }
--- a/jdk/src/share/classes/java/security/cert/X509CertSelector.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/security/cert/X509CertSelector.java	Wed Jul 05 17:50:47 2017 +0200
@@ -2615,7 +2615,7 @@
             return copy;
         } catch (CloneNotSupportedException e) {
             /* Cannot happen */
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 }
--- a/jdk/src/share/classes/java/text/AttributedString.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/text/AttributedString.java	Wed Jul 05 17:50:47 2017 +0200
@@ -794,7 +794,7 @@
                 return other;
             }
             catch (CloneNotSupportedException e) {
-                throw new InternalError();
+                throw new InternalError(e);
             }
         }
 
--- a/jdk/src/share/classes/java/text/BreakDictionary.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/text/BreakDictionary.java	Wed Jul 05 17:50:47 2017 +0200
@@ -154,7 +154,7 @@
             );
         }
         catch (PrivilegedActionException e) {
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
 
         byte[] buf = new byte[8];
--- a/jdk/src/share/classes/java/text/BreakIterator.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/text/BreakIterator.java	Wed Jul 05 17:50:47 2017 +0200
@@ -254,7 +254,7 @@
             return super.clone();
         }
         catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
@@ -617,7 +617,7 @@
             }
         }
         catch (Exception e) {
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 
--- a/jdk/src/share/classes/java/text/Collator.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/text/Collator.java	Wed Jul 05 17:50:47 2017 +0200
@@ -461,7 +461,7 @@
         try {
             return (Collator)super.clone();
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/text/DateFormatSymbols.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/text/DateFormatSymbols.java	Wed Jul 05 17:50:47 2017 +0200
@@ -597,7 +597,7 @@
             copyMembers(this, other);
             return other;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/text/DecimalFormat.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/text/DecimalFormat.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1891,14 +1891,10 @@
      * Standard override; no change in semantics.
      */
     public Object clone() {
-        try {
-            DecimalFormat other = (DecimalFormat) super.clone();
-            other.symbols = (DecimalFormatSymbols) symbols.clone();
-            other.digitList = (DigitList) digitList.clone();
-            return other;
-        } catch (Exception e) {
-            throw new InternalError();
-        }
+        DecimalFormat other = (DecimalFormat) super.clone();
+        other.symbols = (DecimalFormatSymbols) symbols.clone();
+        other.digitList = (DigitList) digitList.clone();
+        return other;
     }
 
     /**
--- a/jdk/src/share/classes/java/text/DecimalFormatSymbols.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/text/DecimalFormatSymbols.java	Wed Jul 05 17:50:47 2017 +0200
@@ -479,7 +479,7 @@
             return (DecimalFormatSymbols)super.clone();
             // other fields are bit-copied
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/text/DigitList.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/text/DigitList.java	Wed Jul 05 17:50:47 2017 +0200
@@ -632,7 +632,7 @@
             other.tempBuffer = null;
             return other;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/text/Format.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/text/Format.java	Wed Jul 05 17:50:47 2017 +0200
@@ -258,7 +258,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // will never happen
-            return null;
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/text/RuleBasedBreakIterator.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/text/RuleBasedBreakIterator.java	Wed Jul 05 17:50:47 2017 +0200
@@ -453,7 +453,7 @@
             );
         }
         catch (PrivilegedActionException e) {
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
 
         int offset = 0;
--- a/jdk/src/share/classes/java/text/StringCharacterIterator.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/text/StringCharacterIterator.java	Wed Jul 05 17:50:47 2017 +0200
@@ -272,7 +272,7 @@
             return other;
         }
         catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/util/ArrayList.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/ArrayList.java	Wed Jul 05 17:50:47 2017 +0200
@@ -307,7 +307,7 @@
             return v;
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/util/BitSet.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/BitSet.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1092,7 +1092,7 @@
             result.checkInvariants();
             return result;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/util/Calendar.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/Calendar.java	Wed Jul 05 17:50:47 2017 +0200
@@ -2512,7 +2512,7 @@
         }
         catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/util/Currency.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/Currency.java	Wed Jul 05 17:50:47 2017 +0200
@@ -221,9 +221,7 @@
                     otherCurrenciesNumericCode = readIntArray(dis, ocCount);
                     dis.close();
                 } catch (IOException e) {
-                    InternalError ie = new InternalError();
-                    ie.initCause(e);
-                    throw ie;
+                    throw new InternalError(e);
                 }
 
                 // look for the properties file for overrides
--- a/jdk/src/share/classes/java/util/HashSet.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/HashSet.java	Wed Jul 05 17:50:47 2017 +0200
@@ -253,7 +253,7 @@
             newSet.map = (HashMap<E, Object>) map.clone();
             return newSet;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/util/Hashtable.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/Hashtable.java	Wed Jul 05 17:50:47 2017 +0200
@@ -537,7 +537,7 @@
             return t;
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/util/IdentityHashMap.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/IdentityHashMap.java	Wed Jul 05 17:50:47 2017 +0200
@@ -703,7 +703,7 @@
             m.table = table.clone();
             return m;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/util/LinkedList.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/LinkedList.java	Wed Jul 05 17:50:47 2017 +0200
@@ -994,7 +994,7 @@
         try {
             return (LinkedList<E>) super.clone();
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/util/Locale.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/Locale.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1859,7 +1859,7 @@
             Locale that = (Locale)super.clone();
             return that;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/util/ResourceBundle.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/ResourceBundle.java	Wed Jul 05 17:50:47 2017 +0200
@@ -614,7 +614,7 @@
                 return clone;
             } catch (CloneNotSupportedException e) {
                 //this should never happen
-                throw new InternalError();
+                throw new InternalError(e);
             }
         }
 
--- a/jdk/src/share/classes/java/util/TimeZone.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/TimeZone.java	Wed Jul 05 17:50:47 2017 +0200
@@ -739,7 +739,7 @@
             other.ID = ID;
             return other;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/util/TreeMap.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/TreeMap.java	Wed Jul 05 17:50:47 2017 +0200
@@ -622,7 +622,7 @@
         try {
             clone = (TreeMap<K,V>) super.clone();
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
 
         // Put clone into "virgin" state (except for comparator)
--- a/jdk/src/share/classes/java/util/TreeSet.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/TreeSet.java	Wed Jul 05 17:50:47 2017 +0200
@@ -474,7 +474,7 @@
         try {
             clone = (TreeSet<E>) super.clone();
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
 
         clone.m = new TreeMap<>(m);
--- a/jdk/src/share/classes/java/util/UUID.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/UUID.java	Wed Jul 05 17:50:47 2017 +0200
@@ -165,7 +165,7 @@
         try {
             md = MessageDigest.getInstance("MD5");
         } catch (NoSuchAlgorithmException nsae) {
-            throw new InternalError("MD5 not supported");
+            throw new InternalError("MD5 not supported", nsae);
         }
         byte[] md5Bytes = md.digest(name);
         md5Bytes[6]  &= 0x0f;  /* clear version        */
--- a/jdk/src/share/classes/java/util/Vector.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/Vector.java	Wed Jul 05 17:50:47 2017 +0200
@@ -673,7 +673,7 @@
             return v;
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/java/util/zip/ZipEntry.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/java/util/zip/ZipEntry.java	Wed Jul 05 17:50:47 2017 +0200
@@ -321,7 +321,7 @@
             return e;
         } catch (CloneNotSupportedException e) {
             // This should never happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 }
--- a/jdk/src/share/classes/javax/management/openmbean/TabularDataSupport.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/javax/management/openmbean/TabularDataSupport.java	Wed Jul 05 17:50:47 2017 +0200
@@ -671,7 +671,7 @@
             return c;
         }
         catch (CloneNotSupportedException e) {
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 
--- a/jdk/src/share/classes/javax/swing/AbstractButton.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/javax/swing/AbstractButton.java	Wed Jul 05 17:50:47 2017 +0200
@@ -981,6 +981,7 @@
      * @param exception the message to use in the
      *        {@code IllegalArgumentException} that is thrown for an invalid
      *        value
+     * @return the {@code key} argument
      * @exception IllegalArgumentException if key is not one of the legal
      *            values listed above
      * @see #setHorizontalTextPosition
@@ -1011,6 +1012,7 @@
      * @param exception the message to use in the
      *        {@code IllegalArgumentException} that is thrown for an invalid
      *        value
+     * @return the {@code key} argument
      * @exception IllegalArgumentException if key is not one of the legal
      *            values listed above
      */
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1153,10 +1153,15 @@
                 if (shellFolder.isLink()) {
                     File linkedTo = shellFolder.getLinkLocation();
 
-                    if (linkedTo != null && fc.isTraversable(linkedTo)) {
-                        dir = linkedTo;
+                    // If linkedTo is null we try to use dir
+                    if (linkedTo != null) {
+                        if (fc.isTraversable(linkedTo)) {
+                            dir = linkedTo;
+                        } else {
+                            return;
+                        }
                     } else {
-                        return;
+                        dir = shellFolder;
                     }
                 }
             } catch (FileNotFoundException ex) {
--- a/jdk/src/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java	Wed Jul 05 17:50:47 2017 +0200
@@ -461,16 +461,16 @@
 
         Locale l = fc.getLocale();
 
-        lookInLabelMnemonic = UIManager.getInt("FileChooser.lookInLabelMnemonic");
+        lookInLabelMnemonic = getMnemonic("FileChooser.lookInLabelMnemonic", l);
         lookInLabelText = UIManager.getString("FileChooser.lookInLabelText",l);
         saveInLabelText = UIManager.getString("FileChooser.saveInLabelText",l);
 
-        fileNameLabelMnemonic = UIManager.getInt("FileChooser.fileNameLabelMnemonic");
+        fileNameLabelMnemonic = getMnemonic("FileChooser.fileNameLabelMnemonic", l);
         fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText",l);
-        folderNameLabelMnemonic = UIManager.getInt("FileChooser.folderNameLabelMnemonic");
+        folderNameLabelMnemonic = getMnemonic("FileChooser.folderNameLabelMnemonic", l);
         folderNameLabelText = UIManager.getString("FileChooser.folderNameLabelText",l);
 
-        filesOfTypeLabelMnemonic = UIManager.getInt("FileChooser.filesOfTypeLabelMnemonic");
+        filesOfTypeLabelMnemonic = getMnemonic("FileChooser.filesOfTypeLabelMnemonic", l);
         filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText",l);
 
         upFolderToolTipText =  UIManager.getString("FileChooser.upFolderToolTipText",l);
@@ -489,6 +489,10 @@
         detailsViewButtonAccessibleName = UIManager.getString("FileChooser.detailsViewButtonAccessibleName",l);
     }
 
+    private Integer getMnemonic(String key, Locale l) {
+        return SwingUtilities2.getUIDefaultsInt(key, l);
+    }
+
     protected void installListeners(JFileChooser fc) {
         super.installListeners(fc);
         ActionMap actionMap = getActionMap();
--- a/jdk/src/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java	Wed Jul 05 17:50:47 2017 +0200
@@ -844,9 +844,6 @@
             "FileChooser.newFolderIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getFileChooserNewFolderIcon"),
             "FileChooser.upFolderIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getFileChooserUpFolderIcon"),
 
-            "FileChooser.lookInLabelMnemonic", new Integer(KeyEvent.VK_I),
-            "FileChooser.fileNameLabelMnemonic", new Integer(KeyEvent.VK_N),
-            "FileChooser.filesOfTypeLabelMnemonic", new Integer(KeyEvent.VK_T),
             "FileChooser.usesSingleFilePane", Boolean.TRUE,
             "FileChooser.ancestorInputMap",
                new UIDefaults.LazyInputMap(new Object[] {
--- a/jdk/src/share/classes/javax/swing/text/ElementIterator.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/javax/swing/text/ElementIterator.java	Wed Jul 05 17:50:47 2017 +0200
@@ -157,7 +157,7 @@
             }
             return it;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/javax/swing/text/rtf/RTFReader.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/javax/swing/text/rtf/RTFReader.java	Wed Jul 05 17:50:47 2017 +0200
@@ -528,7 +528,7 @@
             try {
                 translationTable = (char[])getCharacterSet("ansi");
             } catch (IOException e) {
-                throw new InternalError("RTFReader: Unable to find character set resources (" + e + ")");
+                throw new InternalError("RTFReader: Unable to find character set resources (" + e + ")", e);
             }
         }
     }
@@ -1614,7 +1614,7 @@
         } catch (BadLocationException ble) {
             /* This shouldn't be able to happen, of course */
             /* TODO is InternalError the correct error to throw? */
-            throw new InternalError(ble.getMessage());
+            throw new InternalError(ble.getMessage(), ble);
         }
     }
 
@@ -1628,7 +1628,7 @@
         } catch (BadLocationException ble) {
             /* This shouldn't be able to happen, of course */
             /* TODO is InternalError the correct error to throw? */
-            throw new InternalError(ble.getMessage());
+            throw new InternalError(ble.getMessage(), ble);
         }
     }
 
--- a/jdk/src/share/classes/sun/awt/FontConfiguration.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/awt/FontConfiguration.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, 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
@@ -266,11 +266,20 @@
     private File findFontConfigFile(String javaLib) {
         String baseName = javaLib + File.separator + "fontconfig";
         File configFile;
+        String osMajorVersion = null;
         if (osVersion != null && osName != null) {
             configFile = findImpl(baseName + "." + osName + "." + osVersion);
             if (configFile != null) {
                 return configFile;
             }
+            int decimalPointIndex = osVersion.indexOf(".");
+            if (decimalPointIndex != -1) {
+                osMajorVersion = osVersion.substring(0, osVersion.indexOf("."));
+                configFile = findImpl(baseName + "." + osName + "." + osMajorVersion);
+                if (configFile != null) {
+                    return configFile;
+                }
+            }
         }
         if (osName != null) {
             configFile = findImpl(baseName + "." + osName);
@@ -283,6 +292,12 @@
             if (configFile != null) {
                 return configFile;
             }
+            if (osMajorVersion != null) {
+                configFile = findImpl(baseName + "." + osMajorVersion);
+                if (configFile != null) {
+                    return configFile;
+                }
+            }
         }
         foundOsSpecificFile = false;
 
--- a/jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java	Wed Jul 05 17:50:47 2017 +0200
@@ -158,7 +158,7 @@
             feedConsumer(pi, consumer, normalize, 0.25f);
         } catch (PathException e) {
             throw new InternalError("Unable to Stroke shape ("+
-                                    e.getMessage()+")");
+                                    e.getMessage()+")", e);
         } finally {
             while (consumer != null && consumer != sr) {
                 PathConsumer next = consumer.getConsumer();
@@ -763,7 +763,7 @@
             consumer.endPath();
         } catch (PathException e) {
             throw new InternalError("Unable to Stroke shape ("+
-                                    e.getMessage()+")");
+                                    e.getMessage()+")", e);
         }
     }
 
--- a/jdk/src/share/classes/sun/font/FontLineMetrics.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/font/FontLineMetrics.java	Wed Jul 05 17:50:47 2017 +0200
@@ -113,7 +113,7 @@
             return super.clone();
         }
         catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 }
--- a/jdk/src/share/classes/sun/font/GlyphLayout.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/font/GlyphLayout.java	Wed Jul 05 17:50:47 2017 +0200
@@ -233,7 +233,7 @@
                     invdtx = dtx.createInverse();
                 }
                 catch (NoninvertibleTransformException e) {
-                    throw new InternalError();
+                    throw new InternalError(e);
                 }
             }
 
--- a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java	Wed Jul 05 17:50:47 2017 +0200
@@ -677,9 +677,7 @@
             EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
             NEW_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "newArray", MethodType.methodType(Object[].class, int.class));
         } catch (NoSuchMethodException | IllegalAccessException ex) {
-            Error err = new InternalError("uncaught exception");
-            err.initCause(ex);
-            throw err;
+            throw new InternalError("uncaught exception", ex);
         }
     }
 
@@ -693,9 +691,7 @@
                 COPY_AS_PRIMITIVE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsPrimitiveArray", MethodType.methodType(Object.class, Wrapper.class, Object[].class));
                 MAKE_LIST = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeList", MethodType.methodType(List.class, Object[].class));
             } catch (ReflectiveOperationException ex) {
-                Error err = new InternalError("uncaught exception");
-                err.initCause(ex);
-                throw err;
+                throw new InternalError("uncaught exception", ex);
             }
         }
     }
--- a/jdk/src/share/classes/sun/java2d/pipe/LoopPipe.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/java2d/pipe/LoopPipe.java	Wed Jul 05 17:50:47 2017 +0200
@@ -281,9 +281,8 @@
         } catch (Throwable t) {
             sr.dispose();
             sr = null;
-            t.printStackTrace();
             throw new InternalError("Unable to Stroke shape ("+
-                                    t.getMessage()+")");
+                                    t.getMessage()+")", t);
         }
         return sr;
     }
--- a/jdk/src/share/classes/sun/management/counter/perf/PerfDataEntry.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/management/counter/perf/PerfDataEntry.java	Wed Jul 05 17:50:47 2017 +0200
@@ -133,7 +133,7 @@
         catch (UnsupportedEncodingException e) {
             // should not reach here
             // "UTF-8" is always a known encoding
-            throw new InternalError(e.getMessage());
+            throw new InternalError(e.getMessage(), e);
         }
 
         if (variability == Variability.INVALID) {
--- a/jdk/src/share/classes/sun/management/counter/perf/PerfDataType.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/management/counter/perf/PerfDataType.java	Wed Jul 05 17:50:47 2017 +0200
@@ -93,7 +93,7 @@
             this.value = b[0];
         } catch (UnsupportedEncodingException e) {
             // ignore, "UTF-8" is always a known encoding
-            throw new InternalError("Unknown encoding");
+            throw new InternalError("Unknown encoding", e);
         }
     }
 }
--- a/jdk/src/share/classes/sun/misc/Launcher.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/misc/Launcher.java	Wed Jul 05 17:50:47 2017 +0200
@@ -71,7 +71,7 @@
             extcl = ExtClassLoader.getExtClassLoader();
         } catch (IOException e) {
             throw new InternalError(
-                "Could not create extension class loader");
+                "Could not create extension class loader", e);
         }
 
         // Now create the class loader to use to launch the application
@@ -79,7 +79,7 @@
             loader = AppClassLoader.getAppClassLoader(extcl);
         } catch (IOException e) {
             throw new InternalError(
-                "Could not create application class loader");
+                "Could not create application class loader", e);
         }
 
         // Also set the context class loader for the primordial thread.
@@ -460,7 +460,7 @@
             return ParseUtil.fileToEncodedURL(file);
         } catch (MalformedURLException e) {
             // Should never happen since we specify the protocol...
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
@@ -475,15 +475,10 @@
             try {
                 Class c = Class.forName(name);
                 return (URLStreamHandler)c.newInstance();
-            } catch (ClassNotFoundException e) {
-                e.printStackTrace();
-            } catch (InstantiationException e) {
-                e.printStackTrace();
-            } catch (IllegalAccessException e) {
-                e.printStackTrace();
+            } catch (ReflectiveOperationException e) {
+                throw new InternalError("could not load " + protocol +
+                                        "system protocol handler", e);
             }
-            throw new InternalError("could not load " + protocol +
-                                    "system protocol handler");
         }
     }
 }
--- a/jdk/src/share/classes/sun/misc/ProxyGenerator.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/misc/ProxyGenerator.java	Wed Jul 05 17:50:47 2017 +0200
@@ -460,7 +460,7 @@
             methods.add(generateStaticInitializer());
 
         } catch (IOException e) {
-            throw new InternalError("unexpected I/O Exception");
+            throw new InternalError("unexpected I/O Exception", e);
         }
 
         if (methods.size() > 65535) {
@@ -540,7 +540,7 @@
             dout.writeShort(0); // (no ClassFile attributes for proxy classes)
 
         } catch (IOException e) {
-            throw new InternalError("unexpected I/O Exception");
+            throw new InternalError("unexpected I/O Exception", e);
         }
 
         return bout.toByteArray();
--- a/jdk/src/share/classes/sun/net/NetworkClient.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/net/NetworkClient.java	Wed Jul 05 17:50:47 2017 +0200
@@ -139,7 +139,7 @@
                                         serverSocket.getOutputStream()),
                                         true, encoding);
         } catch (UnsupportedEncodingException e) {
-            throw new InternalError(encoding +"encoding not found");
+            throw new InternalError(encoding +"encoding not found", e);
         }
         serverInput = new BufferedInputStream(serverSocket.getInputStream());
     }
--- a/jdk/src/share/classes/sun/net/NetworkServer.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/net/NetworkServer.java	Wed Jul 05 17:50:47 2017 +0200
@@ -142,7 +142,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/sun/net/ftp/impl/FtpClient.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/net/ftp/impl/FtpClient.java	Wed Jul 05 17:50:47 2017 +0200
@@ -905,7 +905,7 @@
             out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
                     true, encoding);
         } catch (UnsupportedEncodingException e) {
-            throw new InternalError(encoding + "encoding not found");
+            throw new InternalError(encoding + "encoding not found", e);
         }
         in = new BufferedInputStream(server.getInputStream());
     }
@@ -1621,7 +1621,7 @@
                     out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
                             true, encoding);
                 } catch (UnsupportedEncodingException e) {
-                    throw new InternalError(encoding + "encoding not found");
+                    throw new InternalError(encoding + "encoding not found", e);
                 }
                 in = new BufferedInputStream(server.getInputStream());
             }
@@ -2056,7 +2056,7 @@
             out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
                     true, encoding);
         } catch (UnsupportedEncodingException e) {
-            throw new InternalError(encoding + "encoding not found");
+            throw new InternalError(encoding + "encoding not found", e);
         }
         in = new BufferedInputStream(server.getInputStream());
 
@@ -2090,7 +2090,7 @@
             out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
                     true, encoding);
         } catch (UnsupportedEncodingException e) {
-            throw new InternalError(encoding + "encoding not found");
+            throw new InternalError(encoding + "encoding not found", e);
         }
         in = new BufferedInputStream(server.getInputStream());
 
--- a/jdk/src/share/classes/sun/net/smtp/SmtpClient.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/net/smtp/SmtpClient.java	Wed Jul 05 17:50:47 2017 +0200
@@ -134,7 +134,7 @@
         try {
             message = new SmtpPrintStream(serverOutput, this);
         } catch (UnsupportedEncodingException e) {
-            throw new InternalError(encoding+" encoding not found");
+            throw new InternalError(encoding+" encoding not found", e);
         }
         return message;
     }
--- a/jdk/src/share/classes/sun/net/www/http/ChunkedOutputStream.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/net/www/http/ChunkedOutputStream.java	Wed Jul 05 17:50:47 2017 +0200
@@ -79,7 +79,7 @@
             return header;
         } catch (java.io.UnsupportedEncodingException e) {
             /* This should never happen */
-            throw new InternalError(e.getMessage());
+            throw new InternalError(e.getMessage(), e);
         }
     }
 
--- a/jdk/src/share/classes/sun/net/www/http/HttpClient.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/net/www/http/HttpClient.java	Wed Jul 05 17:50:47 2017 +0200
@@ -395,7 +395,7 @@
                 new BufferedOutputStream(out),
                                          false, encoding);
         } catch (UnsupportedEncodingException e) {
-            throw new InternalError(encoding+" encoding not found");
+            throw new InternalError(encoding+" encoding not found", e);
         }
         serverSocket.setTcpNoDelay(true);
     }
--- a/jdk/src/share/classes/sun/net/www/protocol/gopher/GopherClient.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/gopher/GopherClient.java	Wed Jul 05 17:50:47 2017 +0200
@@ -324,7 +324,7 @@
            }
 
        } catch (UnsupportedEncodingException e) {
-            throw new InternalError(encoding+ " encoding not found");
+            throw new InternalError(encoding+ " encoding not found", e);
        } catch (IOException e) {
        } finally {
            try {
--- a/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java	Wed Jul 05 17:50:47 2017 +0200
@@ -529,7 +529,7 @@
                     new BufferedOutputStream(serverSocket.getOutputStream()),
                     false, encoding);
             } catch (UnsupportedEncodingException e) {
-                throw new InternalError(encoding+" encoding not found");
+                throw new InternalError(encoding+" encoding not found", e);
             }
 
             // check URL spoofing if it has not been checked under handshaking
--- a/jdk/src/share/classes/sun/nio/ch/Util.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/Util.java	Wed Jul 05 17:50:47 2017 +0200
@@ -373,7 +373,7 @@
                              NoSuchMethodException    |
                              IllegalArgumentException |
                              ClassCastException x) {
-                        throw new InternalError();
+                        throw new InternalError(x);
                     }
                     return null;
                 }});
@@ -395,7 +395,7 @@
         } catch (InstantiationException |
                  IllegalAccessException |
                  InvocationTargetException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
         return dbb;
     }
@@ -418,7 +418,7 @@
                              NoSuchMethodException |
                              IllegalArgumentException |
                              ClassCastException x) {
-                        throw new InternalError();
+                        throw new InternalError(x);
                     }
                     return null;
                 }});
@@ -440,7 +440,7 @@
         } catch (InstantiationException |
                  IllegalAccessException |
                  InvocationTargetException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
         return dbb;
     }
--- a/jdk/src/share/classes/sun/nio/cs/AbstractCharsetProvider.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/AbstractCharsetProvider.java	Wed Jul 05 17:50:47 2017 +0200
@@ -179,7 +179,9 @@
 
                 public Charset next() {
                     String csn = i.next();
-                    return lookup(csn);
+                    synchronized (AbstractCharsetProvider.this) {
+                        return lookup(csn);
+                    }
                 }
 
                 public void remove() {
--- a/jdk/src/share/classes/sun/reflect/UTF8.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/reflect/UTF8.java	Wed Jul 05 17:50:47 2017 +0200
@@ -52,7 +52,7 @@
             }
         } catch (ArrayIndexOutOfBoundsException e) {
             throw new InternalError
-                ("Bug in sun.reflect bootstrap UTF-8 encoder");
+                ("Bug in sun.reflect bootstrap UTF-8 encoder", e);
         }
         return res;
     }
--- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java	Wed Jul 05 17:50:47 2017 +0200
@@ -25,9 +25,11 @@
 
 package sun.reflect.generics.reflectiveObjects;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.GenericDeclaration;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
+import java.util.Objects;
 
 import sun.reflect.generics.factory.GenericsFactory;
 import sun.reflect.generics.tree.FieldTypeSignature;
@@ -178,4 +180,27 @@
     public int hashCode() {
         return genericDeclaration.hashCode() ^ name.hashCode();
     }
+
+    // Currently vacuous implementations of AnnotatedElement methods.
+    public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+        return false;
+    }
+
+    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+        return null;
+    }
+
+    public Annotation[] getAnnotations() {
+        // Since zero-length, don't need defensive clone
+        return EMPTY_ANNOTATION_ARRAY;
+    }
+
+    public Annotation[] getDeclaredAnnotations() {
+        // Since zero-length, don't need defensive clone
+        return EMPTY_ANNOTATION_ARRAY;
+    }
+
+    private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
 }
--- a/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java	Wed Jul 05 17:50:47 2017 +0200
@@ -292,7 +292,7 @@
                 }
             });
         } catch (Exception e) {
-            throw new InternalError("bouncer cannot be found");
+            throw new InternalError("bouncer cannot be found", e);
         }
     }
 
--- a/jdk/src/share/classes/sun/rmi/transport/LiveRef.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/rmi/transport/LiveRef.java	Wed Jul 05 17:50:47 2017 +0200
@@ -111,7 +111,7 @@
             LiveRef newRef = (LiveRef) super.clone();
             return newRef;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 
--- a/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java	Wed Jul 05 17:50:47 2017 +0200
@@ -151,11 +151,36 @@
     }
 
     /**
+     * Obtains a key for a given etype of a principal with possible new salt
+     * and s2kparams
+     * @param cname NOT null
+     * @param password NOT null
+     * @param etype
+     * @param snp can be NULL
+     * @returns never null
+     */
+    public static EncryptionKey acquireSecretKey(PrincipalName cname,
+            char[] password, int etype, PAData.SaltAndParams snp)
+            throws KrbException {
+        String salt;
+        byte[] s2kparams;
+        if (snp != null) {
+            salt = snp.salt != null ? snp.salt : cname.getSalt();
+            s2kparams = snp.params;
+        } else {
+            salt = cname.getSalt();
+            s2kparams = null;
+        }
+        return acquireSecretKey(password, salt, etype, s2kparams);
+    }
+
+    /**
      * Obtains a key for a given etype with salt and optional s2kparams
      * @param password NOT null
      * @param salt NOT null
      * @param etype
      * @param s2kparams can be NULL
+     * @returns never null
      */
     public static EncryptionKey acquireSecretKey(char[] password,
             String salt, int etype, byte[] s2kparams)
--- a/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java	Wed Jul 05 17:50:47 2017 +0200
@@ -131,13 +131,11 @@
             KrbAsReq asReq, PrincipalName cname)
             throws KrbException, Asn1Exception, IOException {
         int encPartKeyType = rep.encPart.getEType();
-        PAData.SaltAndParams snp =
-                PAData.getSaltAndParams(encPartKeyType, rep.pAData);
-        EncryptionKey dkey = null;
-        dkey = EncryptionKey.acquireSecretKey(password,
-                snp.salt == null ? cname.getSalt() : snp.salt,
+        EncryptionKey dkey = EncryptionKey.acquireSecretKey(
+                cname,
+                password,
                 encPartKeyType,
-                snp.params);
+                PAData.getSaltAndParams(encPartKeyType, rep.pAData));
         decrypt(dkey, asReq);
     }
 
--- a/jdk/src/share/classes/sun/security/krb5/KrbAsReqBuilder.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbAsReqBuilder.java	Wed Jul 05 17:50:47 2017 +0200
@@ -169,34 +169,44 @@
              * from a keytab on acceptor, but unfortunately (?) Java supports
              * acceptor using password. In this case, if the service ticket is
              * encrypted using an etype which we don't have PA-DATA new salt,
-             * using the default salt is normally wrong (say, case-insensitive
+             * using the default salt might be wrong (say, case-insensitive
              * user name). Instead, we would use the new salt of another etype.
              */
 
             String salt = null;     // the saved new salt
-            for (int i=0; i<eTypes.length; i++) {
-                PAData.SaltAndParams snp =
-                        PAData.getSaltAndParams(eTypes[i], paList);
-                // First round, only calculate those with new salt
-                if (snp.salt != null) {
-                    salt = snp.salt;
-                    result[i] = EncryptionKey.acquireSecretKey(password,
-                            snp.salt,
-                            eTypes[i],
-                            snp.params);
-                }
-            }
-            if (salt == null) salt = cname.getSalt();
-            for (int i=0; i<eTypes.length; i++) {
-                // Second round, calculate those with no new salt
-                if (result[i] == null) {
+            try {
+                for (int i=0; i<eTypes.length; i++) {
+                    // First round, only calculate those have a PA entry
                     PAData.SaltAndParams snp =
                             PAData.getSaltAndParams(eTypes[i], paList);
-                    result[i] = EncryptionKey.acquireSecretKey(password,
-                            salt,
-                            eTypes[i],
-                            snp.params);
+                    if (snp != null) {
+                        // Never uses a salt for rc4-hmac, it does not use
+                        // a salt at all
+                        if (eTypes[i] != EncryptedData.ETYPE_ARCFOUR_HMAC &&
+                                snp.salt != null) {
+                            salt = snp.salt;
+                        }
+                        result[i] = EncryptionKey.acquireSecretKey(cname,
+                                password,
+                                eTypes[i],
+                                snp);
+                    }
                 }
+                // No new salt from PA, maybe empty, maybe only rc4-hmac
+                if (salt == null) salt = cname.getSalt();
+                for (int i=0; i<eTypes.length; i++) {
+                    // Second round, calculate those with no PA entry
+                    if (result[i] == null) {
+                        result[i] = EncryptionKey.acquireSecretKey(password,
+                                salt,
+                                eTypes[i],
+                                null);
+                    }
+                }
+            } catch (IOException ioe) {
+                KrbException ke = new KrbException(Krb5.ASN1_PARSE_ERROR);
+                ke.initCause(ioe);
+                throw ke;
             }
             return result;
         } else {
@@ -315,27 +325,19 @@
                     }
                     preAuthFailedOnce = true;
                     KRBError kerr = ke.getError();
+                    int paEType = PAData.getPreferredEType(kerr.getPA(),
+                            EType.getDefaults("default_tkt_enctypes")[0]);
                     if (password == null) {
                         EncryptionKey[] ks = Krb5Util.keysFromJavaxKeyTab(ktab, cname);
-                        pakey = EncryptionKey.findKey(kerr.getEType(), ks);
+                        pakey = EncryptionKey.findKey(paEType, ks);
                         if (pakey != null) pakey = (EncryptionKey)pakey.clone();
                         for (EncryptionKey k: ks) k.destroy();
                     } else {
-                        PAData.SaltAndParams snp = PAData.getSaltAndParams(
-                                kerr.getEType(), kerr.getPA());
-                        if (kerr.getEType() == 0) {
-                            // Possible if PA-PW-SALT is in KRB-ERROR. RFC
-                            // does not recommend this
-                            pakey = EncryptionKey.acquireSecretKey(password,
-                                    snp.salt == null ? cname.getSalt() : snp.salt,
-                                    EType.getDefaults("default_tkt_enctypes")[0],
-                                    null);
-                        } else {
-                            pakey = EncryptionKey.acquireSecretKey(password,
-                                    snp.salt == null ? cname.getSalt() : snp.salt,
-                                    kerr.getEType(),
-                                    snp.params);
-                        }
+                        pakey = EncryptionKey.acquireSecretKey(cname,
+                                password,
+                                paEType,
+                                PAData.getSaltAndParams(
+                                    paEType, kerr.getPA()));
                     }
                     paList = kerr.getPA();  // Update current paList
                 } else {
--- a/jdk/src/share/classes/sun/security/krb5/internal/KRBError.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KRBError.java	Wed Jul 05 17:50:47 2017 +0200
@@ -99,7 +99,6 @@
     private Checksum eCksum; //optional
 
     private PAData[] pa;    // PA-DATA in eData
-    private int pa_eType;   // The 1st etype appeared in salt-related PAData
 
     private static boolean DEBUG = Krb5.DEBUG;
 
@@ -266,50 +265,8 @@
             DerValue tmp = derPA.data.getDerValue();
             PAData pa_data = new PAData(tmp);
             paList.add(pa_data);
-            int pa_type = pa_data.getType();
-            byte[] pa_value = pa_data.getValue();
             if (DEBUG) {
-                System.out.println(">>>Pre-Authentication Data:");
-                System.out.println("\t PA-DATA type = " + pa_type);
-            }
-
-            switch(pa_type) {
-                case Krb5.PA_ENC_TIMESTAMP:
-                    if (DEBUG) {
-                        System.out.println("\t PA-ENC-TIMESTAMP");
-                    }
-                    break;
-                case Krb5.PA_ETYPE_INFO:
-                    if (pa_value != null) {
-                        DerValue der = new DerValue(pa_value);
-                        while (der.data.available() > 0) {
-                            DerValue value = der.data.getDerValue();
-                            ETypeInfo info = new ETypeInfo(value);
-                            if (pa_eType == 0) pa_eType = info.getEType();
-                            if (DEBUG) {
-                                System.out.println("\t PA-ETYPE-INFO etype = " + info.getEType());
-                                System.out.println("\t PA-ETYPE-INFO salt = " + info.getSalt());
-                            }
-                        }
-                    }
-                    break;
-                case Krb5.PA_ETYPE_INFO2:
-                    if (pa_value != null) {
-                        DerValue der = new DerValue(pa_value);
-                        while (der.data.available() > 0) {
-                            DerValue value = der.data.getDerValue();
-                            ETypeInfo2 info2 = new ETypeInfo2(value);
-                            if (pa_eType == 0) pa_eType = info2.getEType();
-                            if (DEBUG) {
-                                System.out.println("\t PA-ETYPE-INFO2 etype = " + info2.getEType());
-                                System.out.println("\t PA-ETYPE-INFO2 salt = " + info2.getSalt());
-                            }
-                        }
-                    }
-                    break;
-                default:
-                    // Unknown Pre-auth type
-                    break;
+                System.out.println(pa_data);
             }
         }
         pa = paList.toArray(new PAData[paList.size()]);
@@ -340,10 +297,6 @@
         return pa;
     }
 
-    public final int getEType() {
-        return pa_eType;
-    }
-
     public final String getErrorString() {
         return eText;
     }
--- a/jdk/src/share/classes/sun/security/krb5/internal/PAData.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/PAData.java	Wed Jul 05 17:50:47 2017 +0200
@@ -139,9 +139,56 @@
     }
 
     /**
+     * Gets the preferred etype from the PAData array.
+     * 1. ETYPE-INFO2-ENTRY with unknown s2kparams ignored
+     * 2. ETYPE-INFO2 preferred to ETYPE-INFO
+     * 3. multiple entries for same etype in one PA-DATA, use the first one.
+     * 4. Multiple PA-DATA with same type, choose the last one
+     * (This is useful when PA-DATAs from KRB-ERROR and AS-REP are combined).
+     * @return the etype, or defaultEType if not enough info
+     * @throws Asn1Exception|IOException if there is an encoding error
+     */
+    public static int getPreferredEType(PAData[] pas, int defaultEType)
+            throws IOException, Asn1Exception {
+
+        if (pas == null) return defaultEType;
+
+        DerValue d = null, d2 = null;
+        for (PAData p: pas) {
+            if (p.getValue() == null) continue;
+            switch (p.getType()) {
+                case Krb5.PA_ETYPE_INFO:
+                    d = new DerValue(p.getValue());
+                    break;
+                case Krb5.PA_ETYPE_INFO2:
+                    d2 = new DerValue(p.getValue());
+                    break;
+            }
+        }
+        if (d2 != null) {
+            while (d2.data.available() > 0) {
+                DerValue value = d2.data.getDerValue();
+                ETypeInfo2 tmp = new ETypeInfo2(value);
+                if (tmp.getParams() == null) {
+                    // we don't support non-null s2kparams
+                    return tmp.getEType();
+                }
+            }
+        }
+        if (d != null) {
+            while (d.data.available() > 0) {
+                DerValue value = d.data.getDerValue();
+                ETypeInfo tmp = new ETypeInfo(value);
+                return tmp.getEType();
+            }
+        }
+        return defaultEType;
+    }
+
+    /**
      * A place to store a pair of salt and s2kparams.
-     * An empty salt is changed to null, to be interopable
-     * with Windows 2000 server.
+     * An empty salt is changed to null, to be interoperable
+     * with Windows 2000 server. This is in fact not correct.
      */
     public static class SaltAndParams {
         public final String salt;
@@ -155,57 +202,120 @@
 
     /**
      * Fetches salt and s2kparams value for eType in a series of PA-DATAs.
-     * The preference order is PA-ETYPE-INFO2 > PA-ETYPE-INFO > PA-PW-SALT.
-     * If multiple PA-DATA for the same etype appears, use the last one.
+     * 1. ETYPE-INFO2-ENTRY with unknown s2kparams ignored
+     * 2. PA-ETYPE-INFO2 preferred to PA-ETYPE-INFO preferred to PA-PW-SALT.
+     * 3. multiple entries for same etype in one PA-DATA, use the first one.
+     * 4. Multiple PA-DATA with same type, choose the last one
      * (This is useful when PA-DATAs from KRB-ERROR and AS-REP are combined).
-     * @return salt and s2kparams. never null, its field might be null.
+     * @return salt and s2kparams. can be null if not found
      */
     public static SaltAndParams getSaltAndParams(int eType, PAData[] pas)
-            throws Asn1Exception, KrbException {
+            throws Asn1Exception, IOException {
 
-        if (pas == null || pas.length == 0) {
-            return new SaltAndParams(null, null);
-        }
+        if (pas == null) return null;
 
+        DerValue d = null, d2 = null;
         String paPwSalt = null;
-        ETypeInfo2 info2 = null;
-        ETypeInfo info = null;
 
         for (PAData p: pas) {
-            if (p.getValue() != null) {
-                try {
-                    switch (p.getType()) {
-                        case Krb5.PA_PW_SALT:
-                            paPwSalt = new String(p.getValue(),
-                                    KerberosString.MSNAME?"UTF8":"8859_1");
-                            break;
-                        case Krb5.PA_ETYPE_INFO:
-                            DerValue der = new DerValue(p.getValue());
-                            while (der.data.available() > 0) {
-                                DerValue value = der.data.getDerValue();
-                                ETypeInfo tmp = new ETypeInfo(value);
-                                if (tmp.getEType() == eType) info = tmp;
-                            }
-                            break;
-                        case Krb5.PA_ETYPE_INFO2:
-                            der = new DerValue(p.getValue());
-                            while (der.data.available() > 0) {
-                                DerValue value = der.data.getDerValue();
-                                ETypeInfo2 tmp = new ETypeInfo2(value);
-                                if (tmp.getEType() == eType) info2 = tmp;
-                            }
-                            break;
-                    }
-                } catch (IOException ioe) {
-                    // Ignored
+            if (p.getValue() == null) continue;
+            switch (p.getType()) {
+                case Krb5.PA_PW_SALT:
+                    paPwSalt = new String(p.getValue(),
+                            KerberosString.MSNAME?"UTF8":"8859_1");
+                    break;
+                case Krb5.PA_ETYPE_INFO:
+                    d = new DerValue(p.getValue());
+                    break;
+                case Krb5.PA_ETYPE_INFO2:
+                    d2 = new DerValue(p.getValue());
+                    break;
+            }
+        }
+        if (d2 != null) {
+            while (d2.data.available() > 0) {
+                DerValue value = d2.data.getDerValue();
+                ETypeInfo2 tmp = new ETypeInfo2(value);
+                if (tmp.getParams() == null && tmp.getEType() == eType) {
+                    // we don't support non-null s2kparams
+                    return new SaltAndParams(tmp.getSalt(), tmp.getParams());
+                }
+            }
+        }
+        if (d != null) {
+            while (d.data.available() > 0) {
+                DerValue value = d.data.getDerValue();
+                ETypeInfo tmp = new ETypeInfo(value);
+                if (tmp.getEType() == eType) {
+                    return new SaltAndParams(tmp.getSalt(), null);
                 }
             }
         }
-        if (info2 != null) {
-            return new SaltAndParams(info2.getSalt(), info2.getParams());
-        } else if (info != null) {
-            return new SaltAndParams(info.getSalt(), null);
+        if (paPwSalt != null) {
+            return new SaltAndParams(paPwSalt, null);
         }
-        return new SaltAndParams(paPwSalt, null);
+        return null;
+    }
+
+    @Override
+    public String toString(){
+        StringBuilder sb = new StringBuilder();
+        sb.append(">>>Pre-Authentication Data:\n\t PA-DATA type = ")
+                .append(pADataType).append('\n');
+
+        switch(pADataType) {
+            case Krb5.PA_ENC_TIMESTAMP:
+                sb.append("\t PA-ENC-TIMESTAMP");
+                break;
+            case Krb5.PA_ETYPE_INFO:
+                if (pADataValue != null) {
+                    try {
+                        DerValue der = new DerValue(pADataValue);
+                        while (der.data.available() > 0) {
+                            DerValue value = der.data.getDerValue();
+                            ETypeInfo info = new ETypeInfo(value);
+                            sb.append("\t PA-ETYPE-INFO etype = ")
+                                    .append(info.getEType())
+                                    .append(", salt = ")
+                                    .append(info.getSalt())
+                                    .append('\n');
+                        }
+                    } catch (IOException|Asn1Exception e) {
+                        sb.append("\t <Unparseable PA-ETYPE-INFO>\n");
+                    }
+                }
+                break;
+            case Krb5.PA_ETYPE_INFO2:
+                if (pADataValue != null) {
+                    try {
+                        DerValue der = new DerValue(pADataValue);
+                        while (der.data.available() > 0) {
+                            DerValue value = der.data.getDerValue();
+                            ETypeInfo2 info2 = new ETypeInfo2(value);
+                            sb.append("\t PA-ETYPE-INFO2 etype = ")
+                                    .append(info2.getEType())
+                                    .append(", salt = ")
+                                    .append(info2.getSalt())
+                                    .append(", s2kparams = ");
+                            byte[] s2kparams = info2.getParams();
+                            if (s2kparams == null) {
+                                sb.append("null\n");
+                            } else if (s2kparams.length == 0) {
+                                sb.append("empty\n");
+                            } else {
+                                sb.append(new sun.misc.HexDumpEncoder()
+                                        .encodeBuffer(s2kparams));
+                            }
+                        }
+                    } catch (IOException|Asn1Exception e) {
+                        sb.append("\t <Unparseable PA-ETYPE-INFO>\n");
+                    }
+                }
+                break;
+            default:
+                // Unknown Pre-auth type
+                break;
+        }
+        return sb.toString();
     }
 }
--- a/jdk/src/share/classes/sun/security/provider/SecureRandom.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/security/provider/SecureRandom.java	Wed Jul 05 17:50:47 2017 +0200
@@ -249,7 +249,7 @@
         try {
             digest = MessageDigest.getInstance ("SHA");
         } catch (NoSuchAlgorithmException e) {
-            throw new InternalError("internal error: SHA-1 not available.");
+            throw new InternalError("internal error: SHA-1 not available.", e);
         }
     }
 }
--- a/jdk/src/share/classes/sun/security/provider/SeedGenerator.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/security/provider/SeedGenerator.java	Wed Jul 05 17:50:47 2017 +0200
@@ -151,7 +151,8 @@
         try {
             md = MessageDigest.getInstance("SHA");
         } catch (NoSuchAlgorithmException nsae) {
-            throw new InternalError("internal error: SHA-1 not available.");
+            throw new InternalError("internal error: SHA-1 not available."
+                    , nsae);
         }
 
         // The current time in millis
@@ -258,7 +259,8 @@
             try {
                 digest = MessageDigest.getInstance("SHA");
             } catch (NoSuchAlgorithmException e) {
-                throw new InternalError("internal error: SHA-1 not available.");
+                throw new InternalError("internal error: SHA-1 not available."
+                        , e);
             }
 
             final ThreadGroup[] finalsg = new ThreadGroup[1];
@@ -311,7 +313,8 @@
                             t.start();
                         } catch (Exception e) {
                             throw new InternalError("internal error: " +
-                                                    "SeedGenerator thread creation error.");
+                                                    "SeedGenerator thread creation error."
+                                    , e);
                         }
 
                         // We wait 250milli quanta, so the minimum wait time
@@ -344,7 +347,8 @@
                 }
             } catch (Exception e) {
                 throw new InternalError("internal error: " +
-                                        "SeedGenerator thread generated an exception.");
+                                        "SeedGenerator thread generated an exception."
+                        , e);
             }
         }
 
@@ -367,7 +371,8 @@
             } catch (Exception e) {
                 if (count <= 0)
                     throw new InternalError("internal error: " +
-                                            "SeedGenerator thread generated an exception.");
+                                            "SeedGenerator thread generated an exception."
+                            ,e);
             }
 
             synchronized(this) {
@@ -533,7 +538,7 @@
             } catch (IOException ioe) {
                 throw new InternalError("URLSeedGenerator " + deviceName +
                                         " generated exception: " +
-                                        ioe.getMessage());
+                                        ioe.getMessage(), ioe);
             }
         }
 
--- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java	Wed Jul 05 17:50:47 2017 +0200
@@ -262,7 +262,7 @@
                 = (HashSet<GeneralNameInterface>)subjectNamesTraversed.clone();
             return clonedState;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 }
--- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java	Wed Jul 05 17:50:47 2017 +0200
@@ -394,7 +394,7 @@
 
             return clonedState;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 }
--- a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java	Wed Jul 05 17:50:47 2017 +0200
@@ -494,7 +494,7 @@
                 return super.clone();
             } catch (CloneNotSupportedException e) {
                 /* Cannot happen */
-                throw new InternalError(e.toString());
+                throw new InternalError(e.toString(), e);
             }
         }
     }
--- a/jdk/src/share/classes/sun/security/tools/JarSigner.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/security/tools/JarSigner.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1506,6 +1506,9 @@
             CertPath cp = certificateFactory.generateCertPath(certs);
             validator.validate(cp, pkixParameters);
         } catch (Exception e) {
+            if (debug) {
+                e.printStackTrace();
+            }
             chainNotValidated = true;
             s.append(tab + rb.getString(".CertPath.not.validated.") +
                     e.getLocalizedMessage() + "]\n");   // TODO
@@ -1562,6 +1565,27 @@
         }
 
         try {
+
+            certificateFactory = CertificateFactory.getInstance("X.509");
+            validator = CertPathValidator.getInstance("PKIX");
+            Set<TrustAnchor> tas = new HashSet<>();
+            try {
+                KeyStore caks = KeyTool.getCacertsKeyStore();
+                if (caks != null) {
+                    Enumeration<String> aliases = caks.aliases();
+                    while (aliases.hasMoreElements()) {
+                        String a = aliases.nextElement();
+                        try {
+                            tas.add(new TrustAnchor((X509Certificate)caks.getCertificate(a), null));
+                        } catch (Exception e2) {
+                            // ignore, when a SecretkeyEntry does not include a cert
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                // Ignore, if cacerts cannot be loaded
+            }
+
             if (providerName == null) {
                 store = KeyStore.getInstance(storetype);
             } else {
@@ -1580,45 +1604,28 @@
                         (rb.getString("Enter.Passphrase.for.keystore."));
             }
 
-            if (nullStream) {
-                store.load(null, storepass);
-            } else {
-                keyStoreName = keyStoreName.replace(File.separatorChar, '/');
-                URL url = null;
-                try {
-                    url = new URL(keyStoreName);
-                } catch (java.net.MalformedURLException e) {
-                    // try as file
-                    url = new File(keyStoreName).toURI().toURL();
-                }
-                InputStream is = null;
-                try {
-                    is = url.openStream();
-                    store.load(is, storepass);
-                } finally {
-                    if (is != null) {
-                        is.close();
+            try {
+                if (nullStream) {
+                    store.load(null, storepass);
+                } else {
+                    keyStoreName = keyStoreName.replace(File.separatorChar, '/');
+                    URL url = null;
+                    try {
+                        url = new URL(keyStoreName);
+                    } catch (java.net.MalformedURLException e) {
+                        // try as file
+                        url = new File(keyStoreName).toURI().toURL();
                     }
-                }
-            }
-            Set<TrustAnchor> tas = new HashSet<>();
-            try {
-                KeyStore caks = KeyTool.getCacertsKeyStore();
-                if (caks != null) {
-                    Enumeration<String> aliases = caks.aliases();
-                    while (aliases.hasMoreElements()) {
-                        String a = aliases.nextElement();
-                        try {
-                            tas.add(new TrustAnchor((X509Certificate)caks.getCertificate(a), null));
-                        } catch (Exception e2) {
-                            // ignore, when a SecretkeyEntry does not include a cert
+                    InputStream is = null;
+                    try {
+                        is = url.openStream();
+                        store.load(is, storepass);
+                    } finally {
+                        if (is != null) {
+                            is.close();
                         }
                     }
                 }
-            } catch (Exception e) {
-                // Ignore, if cacerts cannot be loaded
-            }
-            if (store != null) {
                 Enumeration<String> aliases = store.aliases();
                 while (aliases.hasMoreElements()) {
                     String a = aliases.nextElement();
@@ -1634,14 +1641,13 @@
                         // ignore, when a SecretkeyEntry does not include a cert
                     }
                 }
-            }
-            certificateFactory = CertificateFactory.getInstance("X.509");
-            validator = CertPathValidator.getInstance("PKIX");
-            try {
-                pkixParameters = new PKIXParameters(tas);
-                pkixParameters.setRevocationEnabled(false);
-            } catch (InvalidAlgorithmParameterException ex) {
-                // Only if tas is empty
+            } finally {
+                try {
+                    pkixParameters = new PKIXParameters(tas);
+                    pkixParameters.setRevocationEnabled(false);
+                } catch (InvalidAlgorithmParameterException ex) {
+                    // Only if tas is empty
+                }
             }
         } catch (IOException ioe) {
             throw new RuntimeException(rb.getString("keystore.load.") +
@@ -1805,6 +1811,9 @@
                 CertPath cp = certificateFactory.generateCertPath(Arrays.asList(certChain));
                 validator.validate(cp, pkixParameters);
             } catch (Exception e) {
+                if (debug) {
+                    e.printStackTrace();
+                }
                 chainNotValidated = true;
             }
 
--- a/jdk/src/share/classes/sun/security/tools/KeyTool.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1141,17 +1141,14 @@
             if (token) {
                 keyStore.store(null, null);
             } else {
-                FileOutputStream fout = null;
-                try {
-                    fout = (nullStream ?
-                                        (FileOutputStream)null :
-                                        new FileOutputStream(ksfname));
-                    keyStore.store
-                        (fout,
-                        (storePassNew!=null) ? storePassNew : storePass);
-                } finally {
-                    if (fout != null) {
-                        fout.close();
+                char[] pass = (storePassNew!=null) ? storePassNew : storePass;
+                if (nullStream) {
+                    keyStore.store(null, pass);
+                } else {
+                    ByteArrayOutputStream bout = new ByteArrayOutputStream();
+                    keyStore.store(bout, pass);
+                    try (FileOutputStream fout = new FileOutputStream(ksfname)) {
+                        fout.write(bout.toByteArray());
                     }
                 }
             }
@@ -1399,7 +1396,7 @@
     private char[] promptForKeyPass(String alias, String orig, char[] origPass) throws Exception{
         if (P12KEYSTORE.equalsIgnoreCase(storetype)) {
             return origPass;
-        } else if (!token) {
+        } else if (!token && !protectedPath) {
             // Prompt for key password
             int count;
             for (count = 0; count < 3; count++) {
@@ -1446,7 +1443,7 @@
                 }
             }
         }
-        return null;    // PKCS11
+        return null;    // PKCS11, MSCAPI, or -protected
     }
     /**
      * Creates a new secret key.
--- a/jdk/src/share/classes/sun/security/util/SecurityConstants.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/security/util/SecurityConstants.java	Wed Jul 05 17:50:47 2017 +0200
@@ -127,10 +127,8 @@
                 // AWT present
                 try {
                     return (PermissionFactory<?>)c.newInstance();
-                } catch (InstantiationException x) {
-                    throw new InternalError(x.getMessage());
-                } catch (IllegalAccessException x) {
-                    throw new InternalError(x.getMessage());
+                } catch (ReflectiveOperationException x) {
+                    throw new InternalError(x.getMessage(), x);
                 }
             } else {
                 // AWT not present
--- a/jdk/src/share/classes/sun/text/CompactByteArray.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/text/CompactByteArray.java	Wed Jul 05 17:50:47 2017 +0200
@@ -269,7 +269,7 @@
             if (hashes != null) other.hashes = (int[])hashes.clone();
             return other;
         } catch (CloneNotSupportedException e) {
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/sun/text/normalizer/NormalizerBase.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/text/normalizer/NormalizerBase.java	Wed Jul 05 17:50:47 2017 +0200
@@ -636,7 +636,7 @@
             return copy;
         }
         catch (CloneNotSupportedException e) {
-            throw new InternalError(e.toString());
+            throw new InternalError(e.toString(), e);
         }
     }
 
--- a/jdk/src/share/classes/sun/tools/attach/HotSpotAttachProvider.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/tools/attach/HotSpotAttachProvider.java	Wed Jul 05 17:50:47 2017 +0200
@@ -89,7 +89,7 @@
             if (t instanceof SecurityException) {
                 return result;
             }
-            throw new InternalError();          // shouldn't happen
+            throw new InternalError(t);          // shouldn't happen
         }
 
         for (Object vmid: vms) {
--- a/jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java	Wed Jul 05 17:50:47 2017 +0200
@@ -102,7 +102,7 @@
         try {
             loadAgentLibrary("instrument", args);
         } catch (AgentLoadException x) {
-            throw new InternalError("instrument library is missing in target VM");
+            throw new InternalError("instrument library is missing in target VM", x);
         } catch (AgentInitializationException x) {
             /*
              * Translate interesting errors into the right exception and
@@ -212,7 +212,7 @@
         try {
             return execute(cmd, args);
         } catch (AgentLoadException x) {
-            throw new InternalError("Should not get here");
+            throw new InternalError("Should not get here", x);
         }
     }
 
--- a/jdk/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java	Wed Jul 05 17:50:47 2017 +0200
@@ -135,10 +135,8 @@
         try {
             host = MonitoredHost.getMonitoredHost(new HostIdentifier((String)null));
             vms = host.activeVms();
-        } catch (java.net.URISyntaxException sx) {
-            throw new InternalError(sx.getMessage());
-        } catch (MonitorException mx) {
-            throw new InternalError(mx.getMessage());
+        } catch (java.net.URISyntaxException | MonitorException x) {
+            throw new InternalError(x.getMessage(), x);
         }
         for (Object vmid: vms) {
             if (vmid instanceof Integer) {
--- a/jdk/src/share/classes/sun/tools/tree/Node.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/tools/tree/Node.java	Wed Jul 05 17:50:47 2017 +0200
@@ -108,7 +108,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/share/classes/sun/tracing/dtrace/DTraceProvider.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/tracing/dtrace/DTraceProvider.java	Wed Jul 05 17:50:47 2017 +0200
@@ -26,18 +26,15 @@
 package sun.tracing.dtrace;
 
 import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.annotation.Annotation;
-import java.util.HashMap;
 
 import sun.tracing.ProviderSkeleton;
 import sun.tracing.ProbeSkeleton;
 import com.sun.tracing.Provider;
-import com.sun.tracing.ProviderName;
 import com.sun.tracing.ProbeName;
 import com.sun.tracing.dtrace.Attributes;
 import com.sun.tracing.dtrace.ModuleName;
@@ -140,14 +137,8 @@
         try {
             Constructor cons = proxyClass.getConstructor(constructorParams);
             return (T)cons.newInstance(new Object[] { this });
-        } catch (NoSuchMethodException e) {
-            throw new InternalError(e.toString());
-        } catch (IllegalAccessException e) {
-            throw new InternalError(e.toString());
-        } catch (InstantiationException e) {
-            throw new InternalError(e.toString());
-        } catch (InvocationTargetException e) {
-            throw new InternalError(e.toString());
+        } catch (ReflectiveOperationException e) {
+            throw new InternalError(e.toString(), e);
         }
     }
 
--- a/jdk/src/share/classes/sun/util/calendar/CalendarDate.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/share/classes/sun/util/calendar/CalendarDate.java	Wed Jul 05 17:50:47 2017 +0200
@@ -435,7 +435,7 @@
             return super.clone();
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen
-            throw new InternalError();
+            throw new InternalError(e);
         }
     }
 
--- a/jdk/src/solaris/classes/sun/awt/X11/XBaseMenuWindow.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XBaseMenuWindow.java	Wed Jul 05 17:50:47 2017 +0200
@@ -157,7 +157,7 @@
             try {
                 return super.clone();
             } catch (CloneNotSupportedException ex) {
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         }
 
--- a/jdk/src/solaris/classes/sun/awt/X11/XMenuItemPeer.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XMenuItemPeer.java	Wed Jul 05 17:50:47 2017 +0200
@@ -131,7 +131,7 @@
             try {
                 return super.clone();
             } catch (CloneNotSupportedException ex) {
-                throw new InternalError();
+                throw new InternalError(ex);
             }
         }
 
--- a/jdk/src/solaris/classes/sun/nio/ch/InheritedChannel.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/InheritedChannel.java	Wed Jul 05 17:50:47 2017 +0200
@@ -64,7 +64,7 @@
             dup2(devnull, 2);
         } catch (IOException ioe) {
             // this shouldn't happen
-            throw new InternalError();
+            throw new InternalError(ioe);
         }
     }
 
--- a/jdk/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java	Wed Jul 05 17:50:47 2017 +0200
@@ -304,7 +304,7 @@
             try {
                 b = s.getBytes("UTF-8");
             } catch (java.io.UnsupportedEncodingException x) {
-                throw new InternalError();
+                throw new InternalError(x);
             }
             LinuxVirtualMachine.write(fd, b, 0, b.length);
         }
--- a/jdk/src/solaris/native/sun/awt/fontpath.c	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/solaris/native/sun/awt/fontpath.c	Wed Jul 05 17:50:47 2017 +0200
@@ -1191,8 +1191,16 @@
 
             fontformat = NULL;
             (*FcPatternGetString)(fontPattern, FC_FONTFORMAT, 0, &fontformat);
-            if (fontformat != NULL && strcmp((char*)fontformat, "TrueType")
-                != 0) {
+            /* We only want TrueType fonts but some Linuxes still depend
+             * on Type 1 fonts for some Locale support, so we'll allow
+             * them there.
+             */
+            if (fontformat != NULL
+                && (strcmp((char*)fontformat, "TrueType") != 0)
+#ifdef __linux__
+                && (strcmp((char*)fontformat, "Type 1") != 0)
+#endif
+             ) {
                 continue;
             }
             result = (*FcPatternGetCharSet)(fontPattern,
--- a/jdk/src/windows/native/com/sun/security/auth/module/nt.c	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/windows/native/com/sun/security/auth/module/nt.c	Wed Jul 05 17:50:47 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, 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
@@ -43,6 +43,19 @@
 BOOL getTextualSid(PSID pSid, LPTSTR TextualSid, LPDWORD lpdwBufferLen);
 void DisplayErrorText(DWORD dwLastError);
 
+JNIEXPORT jlong JNICALL
+Java_com_sun_security_auth_module_NTSystem_getImpersonationToken0
+        (JNIEnv *env, jobject obj) {
+    HANDLE impersonationToken = 0;      // impersonation token
+    if (debug) {
+        printf("getting impersonation token\n");
+    }
+    if (getImpersonationToken(&impersonationToken) == FALSE) {
+        return 0;
+    }
+    return (jlong)impersonationToken;
+}
+
 JNIEXPORT void JNICALL
 Java_com_sun_security_auth_module_NTSystem_getCurrent
     (JNIEnv *env, jobject obj, jboolean debugNative) {
@@ -59,7 +72,6 @@
     DWORD numGroups = 0;                // num groups
     LPTSTR *groups = NULL;              // groups array
     long pIndex = -1;                   // index of primaryGroup in groups array
-    HANDLE impersonationToken = 0;      // impersonation token
 
     jfieldID fid;
     jstring jstr;
@@ -100,13 +112,6 @@
         return;
     }
 
-    if (debug) {
-        printf("getting impersonation token\n");
-    }
-    if (getImpersonationToken(&impersonationToken) == FALSE) {
-        return;
-    }
-
     // then set values into NTSystem
 
     fid = (*env)->GetFieldID(env, cls, "userName", "Ljava/lang/String;");
@@ -233,18 +238,6 @@
         (*env)->SetObjectField(env, obj, fid, jgroups);
     }
 
-    fid = (*env)->GetFieldID(env, cls, "impersonationToken", "J");
-    if (fid == 0) {
-        jclass newExcCls =
-            (*env)->FindClass(env, "java/lang/IllegalArgumentException");
-        if (newExcCls == 0) {
-            systemError = TRUE;
-            goto out;
-        }
-        (*env)->ThrowNew(env, newExcCls, "invalid field: impersonationToken");
-    }
-    (*env)->SetLongField(env, obj, fid, (jlong)impersonationToken);
-
 out:
     if (userName != NULL) {
         HeapFree(GetProcessHeap(), 0, userName);
@@ -269,6 +262,7 @@
         }
         HeapFree(GetProcessHeap(), 0, groups);
     }
+    CloseHandle(tokenHandle);
 
     if (systemError && debug) {
         printf("  [getCurrent] System Error: ");
@@ -592,6 +586,7 @@
         }
         return FALSE;
     }
+    CloseHandle(dupToken);
 
     if (debug) {
         printf("  [getImpersonationToken] token = %d\n", *impersonationToken);
@@ -802,6 +797,8 @@
         }
         HeapFree(GetProcessHeap(), 0, groups);
     }
+    CloseHandle(impersonationToken);
+    CloseHandle(tokenHandle);
 }
 */
 
--- a/jdk/src/windows/native/java/net/NetworkInterface.c	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/windows/native/java/net/NetworkInterface.c	Wed Jul 05 17:50:47 2017 +0200
@@ -504,8 +504,7 @@
      */
     if (netaddrCount < 0) {
         netaddrCount = enumAddresses_win(env, ifs, &netaddrP);
-        if ((*env)->ExceptionOccurred(env)) {
-            free_netaddr(netaddrP);
+        if (netaddrCount == -1) {
             return NULL;
         }
     }
--- a/jdk/src/windows/native/java/net/NetworkInterface_winXP.c	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/windows/native/java/net/NetworkInterface_winXP.c	Wed Jul 05 17:50:47 2017 +0200
@@ -194,8 +194,7 @@
     while (curr != NULL) {
         netaddr *netaddrP;
         ret = enumAddresses_win(env, curr, &netaddrP);
-        if ((*env)->ExceptionOccurred(env)) {
-            free_netaddr(netaddrP);
+        if (ret == -1) {
             return -1;
         }
         curr->addrs = netaddrP;
@@ -449,8 +448,7 @@
      */
     if (netaddrCount < 0) {
         netaddrCount = enumAddresses_win(env, ifs, &netaddrP);
-        if ((*env)->ExceptionOccurred(env)) {
-            free_netaddr(netaddrP);
+        if (netaddrCount == -1) {
             return NULL;
         }
     }
--- a/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c	Wed Jul 05 17:50:47 2017 +0200
@@ -576,6 +576,7 @@
 {
     /* fields on this */
     jint port;
+    jint scope;
     jint timeout = (*env)->GetIntField(env, this, psi_timeoutID);
     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
     jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
@@ -755,7 +756,11 @@
         addr = (*env)->GetObjectField (env, socketAddressObj, ia6_ipaddressID);
         (*env)->SetByteArrayRegion (env, addr, 0, 16, (const char *)&him.him6.sin6_addr);
         (*env)->SetIntField(env, socketAddressObj, ia_familyID, IPv6);
-        (*env)->SetIntField(env, socketAddressObj, ia6_scopeidID, him.him6.sin6_scope_id);
+        scope = him.him6.sin6_scope_id;
+        (*env)->SetIntField(env, socketAddressObj, ia6_scopeidID, scope);
+        if(scope>0) {
+            (*env)->SetBooleanField(env, socketAddressObj, ia6_scopeidsetID, JNI_TRUE);
+        }
     }
     /* fields common to AF_INET and AF_INET6 */
 
--- a/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp	Wed Jul 05 17:50:47 2017 +0200
@@ -153,6 +153,11 @@
             break;
         }
         case WM_DESTROY: {
+            HIMC hIMC = ::ImmGetContext(hdlg);
+            if (hIMC != NULL) {
+                ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
+            }
+
             WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(parent, NativeDialogWndProcProp));
             ComCtl32Util::GetInstance().UnsubclassHWND(parent,
                                                        FileDialogWndProc,
--- a/jdk/test/Makefile	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/Makefile	Wed Jul 05 17:50:47 2017 +0200
@@ -423,7 +423,8 @@
 # Stable othervm testruns (minus items from PROBLEM_LIST)
 #   Using samevm has problems, and doesn't help performance as much as others.
 JDK_ALL_TARGETS += jdk_awt
-jdk_awt: $(call TestDirs, com/sun/awt java/awt sun/awt)
+jdk_awt: $(call TestDirs, com/sun/awt java/awt sun/awt \
+         javax/imageio javax/print sun/pisces)
 	$(call RunOthervmBatch)
 
 # Stable samevm testruns (minus items from PROBLEM_LIST)
@@ -486,9 +487,8 @@
 # Stable samevm testruns (minus items from PROBLEM_LIST)
 JDK_ALL_TARGETS += jdk_misc
 jdk_misc: $(call TestDirs, \
-          demo javax/imageio javax/naming javax/print javax/script \
-          javax/smartcardio javax/sound com/sun/java com/sun/jndi \
-	  com/sun/org com/sun/xml sun/misc sun/pisces)
+          demo/jvmti demo/zipfs javax/naming javax/script \
+          javax/smartcardio com/sun/jndi com/sun/xml sun/misc)
 	$(call RunSamevmBatch)
 
 # Stable samevm testruns (minus items from PROBLEM_LIST)
@@ -532,17 +532,15 @@
 jdk_security1: $(call TestDirs, java/security)
 	$(call RunSamevmBatch)
 
-# Stable othervm testruns (minus items from PROBLEM_LIST)
-#   Using samevm has serious problems with these tests
+# Stable samevm testruns (minus items from PROBLEM_LIST)
 JDK_ALL_TARGETS += jdk_security2
-jdk_security2: $(call TestDirs, javax/crypto com/sun/crypto)
+jdk_security2: $(call TestDirs, javax/crypto javax/xml/crypto com/sun/crypto)
 	$(call RunSamevmBatch)
 
-# Stable othervm testruns (minus items from PROBLEM_LIST)
-#   Using samevm has serious problems with these tests
+# Stable samevm testruns (minus items from PROBLEM_LIST)
 JDK_ALL_TARGETS += jdk_security3
-jdk_security3: $(call TestDirs, com/sun/security lib/security \
-               javax/security sun/security)
+jdk_security3: $(call TestDirs, com/sun/security lib/security javax/security \
+        sun/security com/sun/org/apache/xml/internal/security)
 	$(call SharedLibraryPermissions,sun/security)
 	$(call RunSamevmBatch)
 
@@ -550,10 +548,16 @@
 jdk_security: jdk_security1 jdk_security2 jdk_security3
 	@$(SummaryInfo)
 
+# Stable samevm testruns (minus items from PROBLEM_LIST)
+JDK_ALL_TARGETS += jdk_sound
+jdk_sound: $(call TestDirs, javax/sound)
+	$(call RunSamevmBatch)
+
 # Stable othervm testruns (minus items from PROBLEM_LIST)
 #   Using samevm has problems, and doesn't help performance as much as others.
 JDK_ALL_TARGETS += jdk_swing
-jdk_swing: $(call TestDirs, javax/swing sun/java2d)
+jdk_swing: $(call TestDirs, javax/swing sun/java2d \
+           demo/jfc com/sun/java/swing)
 	$(call RunOthervmBatch)
 
 # Stable samevm testruns (minus items from PROBLEM_LIST)
@@ -802,17 +806,17 @@
 # The jtjck.jar utility to use to run the tests
 JTJCK_JAR = $(JCK_HOME)/lib/jtjck.jar
 JTJCK_JAVA_ARGS =  -XX:MaxPermSize=256m -Xmx512m
-JTJCK_OPTIONS = -headless -v 
+JTJCK_OPTIONS = -headless -v
 
 # Default tests to run
 ifndef JCK_COMPILER_TESTS
-  JCK_COMPILER_TESTS = 
+  JCK_COMPILER_TESTS =
 endif
 ifndef JCK_RUNTIME_TESTS
-  JCK_RUNTIME_TESTS  = 
+  JCK_RUNTIME_TESTS  =
 endif
 ifndef JCK_DEVTOOLS_TESTS
-  JCK_DEVTOOLS_TESTS = 
+  JCK_DEVTOOLS_TESTS =
 endif
 
 # Generic rule used to run jck tests
@@ -838,14 +842,14 @@
                 _generic_jck_tests
 
 # JCK7 runtime tests
-jck7runtime: 
+jck7runtime:
 	$(MAKE) UNIQUE_DIR=$@ \
 	        JCK_HOME=$(JCK7RUNTIME_HOME) \
 	        TESTDIRS="$(JCK_RUNTIME_TESTS)" \
                 _generic_jck_tests
 
 # JCK7 devtools tests
-jck7devtools: 
+jck7devtools:
 	$(MAKE) UNIQUE_DIR=$@ \
 	        JCK_HOME=$(JCK7DEVTOOLS_HOME) \
                 TESTDIRS="$(JCK_DEVTOOLS_TESTS)" \
--- a/jdk/test/ProblemList.txt	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 17:50:47 2017 +0200
@@ -526,6 +526,16 @@
 # 7081817
 sun/security/provider/certpath/X509CertPath/IllegalCertiticates.java 	generic-all
 
+# 7041639, Solaris DSA keypair generation bug (Note: jdk_util also affected)
+java/security/KeyPairGenerator/SolarisShortDSA.java             solaris-all
+sun/security/tools/jarsigner/onlymanifest.sh                    solaris-all
+sun/security/tools/jarsigner/ts.sh                              solaris-all
+sun/security/tools/keytool/emptysubject.sh                      solaris-all
+sun/security/tools/keytool/importreadall.sh                     solaris-all
+sun/security/tools/keytool/readjar.sh                           solaris-all
+sun/security/tools/keytool/selfissued.sh                        solaris-all
+sun/security/tools/keytool/standard.sh                          solaris-all
+
 ############################################################################
 
 # jdk_swing (not using samevm)
@@ -586,5 +596,8 @@
 # Filed 6772009
 java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java generic-all
 
+# 7041639, Solaris DSA keypair generation bug
+java/util/TimeZone/TimeZoneDatePermissionCheck.sh               solaris-all
+
 ############################################################################
 
--- a/jdk/test/com/sun/servicetag/JavaServiceTagTest.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/com/sun/servicetag/JavaServiceTagTest.java	Wed Jul 05 17:50:47 2017 +0200
@@ -25,7 +25,7 @@
 
 /*
  * @test
- * @bug     6622366
+ * @bug     6622366 7078024
  * @summary Basic Test for ServiceTag.getJavaServiceTag()
  *          Disable creating the service tag in the system registry.
  *          Verify the existence of registration.xml file and the
@@ -86,23 +86,42 @@
         }
     }
 
+    /**
+     * Tests if the running platform is a JDK.
+     */
+    static boolean isJDK() {
+        // Determine the JRE path by checking the existence of
+        // <HOME>/jre/lib and <HOME>/lib.
+        String javaHome = System.getProperty("java.home");
+        String jrepath = javaHome + File.separator + "jre";
+        File f = new File(jrepath, "lib");
+        if (!f.exists()) {
+            // java.home usually points to the JRE path
+            jrepath = javaHome;
+        }
+
+        return jrepath.endsWith(File.separator + "jre");
+    }
+
     private static void checkServiceTag(ServiceTag st) throws IOException {
-        Properties props = loadSwordfishEntries();
-        if (st.getProductURN().
-                equals(props.getProperty("servicetag.jdk.urn"))) {
-            if (!st.getProductName().
-                    equals(props.getProperty("servicetag.jdk.name"))) {
-                throw new RuntimeException("Product URN and name don't match.");
-            }
-        } else if (st.getProductURN().
-                equals(props.getProperty("servicetag.jre.urn"))) {
-            if (!st.getProductName().
-                    equals(props.getProperty("servicetag.jre.name"))) {
+        Properties props = loadServiceTagProps();
+        // jdk 8 and later, JDK and JRE have the same product URN.
+        String jdkUrn = props.getProperty("servicetag.jdk.urn");
+        String jreUrn = props.getProperty("servicetag.jre.urn");
+        boolean isJdk = isJDK();
+
+        if (isJdk) {
+            if (!st.getProductURN().equals(jdkUrn) ||
+                    !st.getProductName().equals(
+                         props.getProperty("servicetag.jdk.name"))) {
                 throw new RuntimeException("Product URN and name don't match.");
             }
         } else {
-            throw new RuntimeException("Unexpected product_urn: " +
-                st.getProductURN());
+            if (!st.getProductURN().equals(jreUrn) ||
+                    !st.getProductName().equals(
+                        props.getProperty("servicetag.jre.name"))) {
+                throw new RuntimeException("Product URN and name don't match.");
+            }
         }
         if (!st.getProductVersion().
                 equals(System.getProperty("java.version"))) {
@@ -160,18 +179,13 @@
         }
     }
 
-    private static Properties loadSwordfishEntries()
+    private static Properties loadServiceTagProps()
            throws IOException {
-        int version = sun.misc.Version.jdkMinorVersion();
-        String filename = "/com/sun/servicetag/resources/javase_" +
-                version + "_swordfish.properties";
-        InputStream in = Installer.class.getClass().getResourceAsStream(filename);
-        Properties props = new Properties();
-        try {
+        String filename = "/com/sun/servicetag/resources/javase_servicetag.properties";
+        try (InputStream in = Installer.class.getClass().getResourceAsStream(filename)) {
+            Properties props = new Properties();
             props.load(in);
-        } finally {
-            in.close();
+            return props;
         }
-        return props;
     }
 }
--- a/jdk/test/com/sun/servicetag/JavaServiceTagTest1.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/com/sun/servicetag/JavaServiceTagTest1.java	Wed Jul 05 17:50:47 2017 +0200
@@ -25,7 +25,7 @@
 
 /*
  * @test
- * @bug     6622366
+ * @bug     6622366 7078024
  * @summary Basic Test for ServiceTag.getJavaServiceTag(String)
  *          to verify that the registration.xml and servicetag files
  *          are both created correctly.
@@ -157,25 +157,45 @@
         return svctag;
     }
 
+    /**
+     * Tests if the running platform is a JDK.
+     */
+    static boolean isJDK() {
+        // Determine the JRE path by checking the existence of
+        // <HOME>/jre/lib and <HOME>/lib.
+        String javaHome = System.getProperty("java.home");
+        String jrepath = javaHome + File.separator + "jre";
+        File f = new File(jrepath, "lib");
+        if (!f.exists()) {
+            // java.home usually points to the JRE path
+            jrepath = javaHome;
+        }
+
+        return jrepath.endsWith(File.separator + "jre");
+    }
+
     private static void checkServiceTag(ServiceTag st, String source)
             throws IOException {
-        Properties props = loadSwordfishEntries();
-        if (st.getProductURN().
-                equals(props.getProperty("servicetag.jdk.urn"))) {
-            if (!st.getProductName().
-                    equals(props.getProperty("servicetag.jdk.name"))) {
-                throw new RuntimeException("Product URN and name don't match.");
-            }
-        } else if (st.getProductURN().
-                equals(props.getProperty("servicetag.jre.urn"))) {
-            if (!st.getProductName().
-                    equals(props.getProperty("servicetag.jre.name"))) {
+        Properties props = loadServiceTagProps();
+        // jdk 8 and later, JDK and JRE have the same product URN.
+        String jdkUrn = props.getProperty("servicetag.jdk.urn");
+        String jreUrn = props.getProperty("servicetag.jre.urn");
+        boolean isJdk = isJDK();
+
+        if (isJdk) {
+            if (!st.getProductURN().equals(jdkUrn) ||
+                    !st.getProductName().equals(
+                         props.getProperty("servicetag.jdk.name"))) {
                 throw new RuntimeException("Product URN and name don't match.");
             }
         } else {
-            throw new RuntimeException("Unexpected product_urn: " +
-                st.getProductURN());
+            if (!st.getProductURN().equals(jreUrn) ||
+                    !st.getProductName().equals(
+                        props.getProperty("servicetag.jre.name"))) {
+                throw new RuntimeException("Product URN and name don't match.");
+            }
         }
+
         if (!st.getProductVersion().
                 equals(System.getProperty("java.version"))) {
             throw new RuntimeException("Unexpected product_version: " +
@@ -233,18 +253,13 @@
         }
     }
 
-    private static Properties loadSwordfishEntries()
+    private static Properties loadServiceTagProps()
            throws IOException {
-        int version = sun.misc.Version.jdkMinorVersion();
-        String filename = "/com/sun/servicetag/resources/javase_" +
-                version + "_swordfish.properties";
-        InputStream in = Installer.class.getClass().getResourceAsStream(filename);
-        Properties props = new Properties();
-        try {
+        String filename = "/com/sun/servicetag/resources/javase_servicetag.properties";
+        try (InputStream in = Installer.class.getClass().getResourceAsStream(filename)) {
+            Properties props = new Properties();
             props.load(in);
-        } finally {
-            in.close();
+            return props;
         }
-        return props;
     }
 }
--- a/jdk/test/java/lang/invoke/InvokeGenericTest.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/java/lang/invoke/InvokeGenericTest.java	Wed Jul 05 17:50:47 2017 +0200
@@ -25,7 +25,7 @@
 
 /* @test
  * @summary unit tests for java.lang.invoke.MethodHandle.invoke
- * @compile -target 7 InvokeGenericTest.java
+ * @compile InvokeGenericTest.java
  * @run junit/othervm test.java.lang.invoke.InvokeGenericTest
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/TypeVariable/TestAnnotatedElement.java	Wed Jul 05 17:50:47 2017 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011, 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 7086192
+ * @summary Verify functionality of AnnotatedElement methods on type variables
+ * @author Joseph D. Darcy
+ */
+
+import java.lang.reflect.*;
+import java.lang.annotation.*;
+
+public class TestAnnotatedElement<A> {
+    // Type variable on a method
+    private static <B> B m(B b) {return null;}
+
+    // Type variable on a construtor
+    private <C> TestAnnotatedElement(){super();}
+
+    public static void main(String... argv) throws ReflectiveOperationException {
+        int errors = 0;
+
+        Class<?> clazz = TestAnnotatedElement.class;
+        errors += testTypeVariable(clazz.getTypeParameters());
+        errors += testTypeVariable(clazz.getDeclaredConstructor().getTypeParameters());
+        errors += testTypeVariable(clazz.getDeclaredMethod("m", Object.class).getTypeParameters());
+
+        if (errors > 0)
+            throw new RuntimeException(errors + " failures");
+    }
+
+
+    private static int testTypeVariable(TypeVariable<?>[] typeVars) {
+        int errors = 0;
+        if (typeVars.length == 0)
+            return ++errors;
+
+        for(TypeVariable<?> typeVar : typeVars) {
+            try {
+                typeVar.getAnnotation(null);
+                errors++;
+            } catch(NullPointerException npe) {
+                ; // Expected
+            }
+
+            if (typeVar.getAnnotation(SuppressWarnings.class) != null)
+                errors++;
+
+            try {
+                typeVar.isAnnotationPresent(null);
+                errors++;
+            } catch(NullPointerException npe) {
+                ; // Expected
+            }
+
+            if (typeVar.isAnnotationPresent(SuppressWarnings.class))
+                errors++;
+
+            if(typeVar.getAnnotations().length != 0)
+                errors++;
+
+            if(typeVar.getDeclaredAnnotations().length != 0)
+                errors++;
+        }
+        return errors;
+    }
+}
--- a/jdk/test/java/math/BigDecimal/DivideMcTests.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/java/math/BigDecimal/DivideMcTests.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
--- a/jdk/test/java/math/BigDecimal/FloatDoubleValueTests.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/java/math/BigDecimal/FloatDoubleValueTests.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6274390
+ * @bug 6274390 7082971
  * @summary Verify {float, double}Value methods work with condensed representation
  * @run main FloatDoubleValueTests
  * @run main/othervm -XX:+AggressiveOpts FloatDoubleValueTests
@@ -79,6 +79,7 @@
     // and double.
     static void testFloatDoubleValue() {
         long longValues[] = {
+            Long.MIN_VALUE, // -2^63
             0,
             1,
             2,
--- a/jdk/test/java/math/BigDecimal/RangeTests.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/java/math/BigDecimal/RangeTests.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
--- a/jdk/test/java/math/BigDecimal/StrippingZerosTest.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/java/math/BigDecimal/StrippingZerosTest.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011 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
--- a/jdk/test/java/math/BigDecimal/ToPlainStringTests.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/java/math/BigDecimal/ToPlainStringTests.java	Wed Jul 05 17:50:47 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2011, 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/Socket/ShutdownInput.java	Wed Jul 05 17:50:47 2017 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011, 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 7014860
+ * @summary Socket.getInputStream().available() not clear for
+ *          case that connection is shutdown for reading
+ */
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+public class ShutdownInput {
+    static boolean failed = false;
+
+    public static void main(String args[]) throws Exception {
+        InetAddress iaddr = InetAddress.getLocalHost();
+
+        try ( ServerSocket ss = new ServerSocket(0);
+              Socket s1 = new Socket(iaddr, ss.getLocalPort());
+              Socket s2 = ss.accept() ) {
+
+            test(s1, s2, "Testing NET");
+        }
+
+        // check the NIO socket adapter
+        try (ServerSocketChannel sc = ServerSocketChannel.open().bind(null);
+             SocketChannel s1 = SocketChannel.open(
+                     new InetSocketAddress(iaddr, sc.socket().getLocalPort()));
+             SocketChannel s2 = sc.accept() ) {
+
+            test(s1.socket(), s2.socket(), "Testing NIO");
+        }
+
+        if (failed) {
+            throw new RuntimeException("Failed: check output");
+        }
+    }
+
+    public static void test(Socket s1, Socket s2, String mesg) throws Exception {
+        OutputStream os = s1.getOutputStream();
+        os.write("This is a message".getBytes("US-ASCII"));
+
+        InputStream in = s2.getInputStream();
+        s2.shutdownInput();
+
+        if (in.available() != 0) {
+            failed = true;
+            System.out.println(mesg + ":" + s2 + " in.available() should be 0, " +
+                               "but returns "+ in.available());
+        }
+
+        byte[] ba = new byte[2];
+        if (in.read() != -1 ||
+            in.read(ba) != -1 ||
+            in.read(ba, 0, ba.length) != -1) {
+
+            failed = true;
+            System.out.append(mesg + ":" + s2 + " in.read() should be -1");
+        }
+    }
+}
--- a/jdk/test/java/net/URI/Test.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/java/net/URI/Test.java	Wed Jul 05 17:50:47 2017 +0200
@@ -23,7 +23,7 @@
 
 /* @test
  * @summary Unit test for java.net.URI
- * @bug 4464135 4505046 4503239 4438319 4991359 4866303 7023363
+ * @bug 4464135 4505046 4503239 4438319 4991359 4866303 7023363 7041800
  * @author Mark Reinhold
  */
 
@@ -1428,6 +1428,8 @@
         gt(s, new URI("http://jag:CafeBabe@java.sun.com:94/b/c/d?q#f"));
         lt(s, new URI("http://jag:cafebabe@java.sun.com:94/b/c/d?r#f"));
         lt(s, new URI("http://jag:cafebabe@java.sun.com:94/b/c/d?q#g"));
+        eq(new URI("http://host/a%00bcd"), new URI("http://host/a%00bcd"));
+        ne(new URI("http://host/a%00bcd"), new URI("http://host/aZ00bcd"));
 
         lt("p", "s:p");
         lt("s:p", "T:p");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/KeyPairGenerator/SolarisShortDSA.java	Wed Jul 05 17:50:47 2017 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011, 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 7081411
+ * @summary DSA keypair generation affected by Solaris bug
+ */
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.Signature;
+import sun.security.provider.DSAPrivateKey;
+
+public class SolarisShortDSA {
+    static byte[] data = new byte[0];
+    public static void main(String args[]) throws Exception {
+        for (int i=0; i<10000; i++) {
+            KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
+            KeyPair kp = kpg.generateKeyPair();
+            DSAPrivateKey dpk = (DSAPrivateKey)kp.getPrivate();
+            int len = dpk.getX().bitLength();
+            if (len <= 152) {
+                if (!use(kp)) {
+                    String os = System.getProperty("os.name");
+                    // Solaris bug, update the following line once it's fixed
+                    if (os.equals("SunOS")) {
+                        throw new IllegalStateException(
+                                "Don't panic. This is a Solaris bug");
+                    } else {
+                        throw new RuntimeException("Real test failure");
+                    }
+                }
+                break;
+            }
+        }
+    }
+
+    static boolean use(KeyPair kp) throws Exception {
+        Signature sig = Signature.getInstance("SHA1withDSA");
+        sig.initSign(kp.getPrivate());
+        sig.update(data);
+        byte[] signed = sig.sign();
+        Signature sig2 = Signature.getInstance("SHA1withDSA");
+        sig2.initVerify(kp.getPublic());
+        sig2.update(data);
+        return sig2.verify(signed);
+   }
+}
--- a/jdk/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java	Wed Jul 05 17:50:47 2017 +0200
@@ -26,6 +26,7 @@
  * @bug 6436919 6460930
  * @summary check that XML Signatures can be generated and validated with
  *  SecurityManager enabled and default policy
+ * @run main/othervm XMLDSigWithSecMgr
  * @author Sean Mullan
  */
 import java.io.*;
--- a/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -54,19 +54,16 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    TMP=/tmp
     ;;
   CYGWIN* )
     NULL=/dev/null
     PS=";"
     FS="/"
-    TMP=/tmp
     ;;
   Windows_95 | Windows_98 | Windows_NT )
     NULL=NUL
     PS=";"
     FS="\\"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized system!"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/DupEtypes.java	Wed Jul 05 17:50:47 2017 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011, 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 7067974
+ * @summary multiple ETYPE-INFO-ENTRY with same etype and different salt
+ * @compile -XDignore.symbol.file DupEtypes.java
+ * @run main/othervm DupEtypes 1
+ * @run main/othervm DupEtypes 2
+ * @run main/othervm/fail DupEtypes 3
+ * @run main/othervm DupEtypes 4
+ * @run main/othervm DupEtypes 5
+ */
+
+import sun.security.jgss.GSSUtil;
+
+public class DupEtypes {
+
+    public static void main(String[] args) throws Exception {
+
+        OneKDC kdc = new OneKDC(null);
+        kdc.writeJAASConf();
+
+        // Different test cases, read KDC.processAsReq for details
+        kdc.setOption(KDC.Option.DUP_ETYPE, Integer.parseInt(args[0]));
+
+        Context c, s;
+        c = Context.fromJAAS("client");
+        s = Context.fromJAAS("server");
+
+        c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+        Context.handshake(c, s);
+
+        Context.transmit("i say high --", c, s);
+        Context.transmit("   you say low", s, c);
+
+        s.dispose();
+        c.dispose();
+    }
+}
--- a/jdk/test/sun/security/krb5/auto/KDC.java	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/krb5/auto/KDC.java	Wed Jul 05 17:50:47 2017 +0200
@@ -174,6 +174,10 @@
          * Set all name-type to a value in response
          */
         RESP_NT,
+        /**
+         * Multiple ETYPE-INFO-ENTRY with same etype but different salt
+         */
+        DUP_ETYPE,
     };
 
     static {
@@ -881,48 +885,104 @@
             bFlags[Krb5.TKT_OPTS_INITIAL] = true;
 
             // Creating PA-DATA
-            int[] epas = eTypes;
-            if (options.containsKey(KDC.Option.RC4_FIRST_PREAUTH)) {
-                for (int i=1; i<epas.length; i++) {
-                    if (epas[i] == EncryptedData.ETYPE_ARCFOUR_HMAC) {
-                        epas[i] = epas[0];
-                        epas[0] = EncryptedData.ETYPE_ARCFOUR_HMAC;
+            DerValue[] pas2 = null, pas = null;
+            if (options.containsKey(KDC.Option.DUP_ETYPE)) {
+                int n = (Integer)options.get(KDC.Option.DUP_ETYPE);
+                switch (n) {
+                    case 1:     // customer's case in 7067974
+                        pas2 = new DerValue[] {
+                            new DerValue(new ETypeInfo2(1, null, null).asn1Encode()),
+                            new DerValue(new ETypeInfo2(1, "", null).asn1Encode()),
+                            new DerValue(new ETypeInfo2(1, OneKDC.REALM, new byte[]{1}).asn1Encode()),
+                        };
+                        pas = new DerValue[] {
+                            new DerValue(new ETypeInfo(1, null).asn1Encode()),
+                            new DerValue(new ETypeInfo(1, "").asn1Encode()),
+                            new DerValue(new ETypeInfo(1, OneKDC.REALM).asn1Encode()),
+                        };
+                        break;
+                    case 2:     // we still reject non-null s2kparams and prefer E2 over E
+                        pas2 = new DerValue[] {
+                            new DerValue(new ETypeInfo2(1, OneKDC.REALM, new byte[]{1}).asn1Encode()),
+                            new DerValue(new ETypeInfo2(1, null, null).asn1Encode()),
+                            new DerValue(new ETypeInfo2(1, "", null).asn1Encode()),
+                        };
+                        pas = new DerValue[] {
+                            new DerValue(new ETypeInfo(1, OneKDC.REALM).asn1Encode()),
+                            new DerValue(new ETypeInfo(1, null).asn1Encode()),
+                            new DerValue(new ETypeInfo(1, "").asn1Encode()),
+                        };
+                        break;
+                    case 3:     // but only E is wrong
+                        pas = new DerValue[] {
+                            new DerValue(new ETypeInfo(1, OneKDC.REALM).asn1Encode()),
+                            new DerValue(new ETypeInfo(1, null).asn1Encode()),
+                            new DerValue(new ETypeInfo(1, "").asn1Encode()),
+                        };
+                        break;
+                    case 4:     // we also ignore rc4-hmac
+                        pas = new DerValue[] {
+                            new DerValue(new ETypeInfo(23, "ANYTHING").asn1Encode()),
+                            new DerValue(new ETypeInfo(1, null).asn1Encode()),
+                            new DerValue(new ETypeInfo(1, "").asn1Encode()),
+                        };
+                        break;
+                    case 5:     // "" should be wrong, but we accept it now
+                                // See s.s.k.internal.PAData$SaltAndParams
+                        pas = new DerValue[] {
+                            new DerValue(new ETypeInfo(1, "").asn1Encode()),
+                            new DerValue(new ETypeInfo(1, null).asn1Encode()),
+                        };
+                        break;
+                }
+            } else {
+                int[] epas = eTypes;
+                if (options.containsKey(KDC.Option.RC4_FIRST_PREAUTH)) {
+                    for (int i=1; i<epas.length; i++) {
+                        if (epas[i] == EncryptedData.ETYPE_ARCFOUR_HMAC) {
+                            epas[i] = epas[0];
+                            epas[0] = EncryptedData.ETYPE_ARCFOUR_HMAC;
+                            break;
+                        }
+                    };
+                } else if (options.containsKey(KDC.Option.ONLY_ONE_PREAUTH)) {
+                    epas = new int[] { eTypes[0] };
+                }
+                pas2 = new DerValue[epas.length];
+                for (int i=0; i<epas.length; i++) {
+                    pas2[i] = new DerValue(new ETypeInfo2(
+                            epas[i],
+                            epas[i] == EncryptedData.ETYPE_ARCFOUR_HMAC ?
+                                null : getSalt(body.cname),
+                            null).asn1Encode());
+                }
+                boolean allOld = true;
+                for (int i: eTypes) {
+                    if (i == EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96 ||
+                            i == EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96) {
+                        allOld = false;
                         break;
                     }
-                };
-            } else if (options.containsKey(KDC.Option.ONLY_ONE_PREAUTH)) {
-                epas = new int[] { eTypes[0] };
+                }
+                if (allOld) {
+                    pas = new DerValue[epas.length];
+                    for (int i=0; i<epas.length; i++) {
+                        pas[i] = new DerValue(new ETypeInfo(
+                                epas[i],
+                                epas[i] == EncryptedData.ETYPE_ARCFOUR_HMAC ?
+                                    null : getSalt(body.cname)
+                                ).asn1Encode());
+                    }
+                }
             }
 
-            DerValue[] pas = new DerValue[epas.length];
-            for (int i=0; i<epas.length; i++) {
-                pas[i] = new DerValue(new ETypeInfo2(
-                        epas[i],
-                        epas[i] == EncryptedData.ETYPE_ARCFOUR_HMAC ?
-                            null : getSalt(body.cname),
-                        null).asn1Encode());
+            DerOutputStream eid;
+            if (pas2 != null) {
+                eid = new DerOutputStream();
+                eid.putSequence(pas2);
+                outPAs.add(new PAData(Krb5.PA_ETYPE_INFO2, eid.toByteArray()));
             }
-            DerOutputStream eid = new DerOutputStream();
-            eid.putSequence(pas);
-
-            outPAs.add(new PAData(Krb5.PA_ETYPE_INFO2, eid.toByteArray()));
-
-            boolean allOld = true;
-            for (int i: eTypes) {
-                if (i == EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96 ||
-                        i == EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96) {
-                    allOld = false;
-                    break;
-                }
-            }
-            if (allOld) {
-                for (int i=0; i<epas.length; i++) {
-                    pas[i] = new DerValue(new ETypeInfo(
-                            epas[i],
-                            epas[i] == EncryptedData.ETYPE_ARCFOUR_HMAC ?
-                                null : getSalt(body.cname)
-                            ).asn1Encode());
-                }
+            if (pas != null) {
                 eid = new DerOutputStream();
                 eid.putSequence(pas);
                 outPAs.add(new PAData(Krb5.PA_ETYPE_INFO, eid.toByteArray()));
--- a/jdk/test/sun/security/tools/jarsigner/AlgOptions.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/jarsigner/AlgOptions.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -51,21 +51,18 @@
     PS=":"
     FS="/"
     CP="${FS}bin${FS}cp -f"
-    TMP=/tmp
     ;;
   CYGWIN* )
     NULL=/dev/null
     PS=";"
     FS="/"
     CP="cp -f"
-    TMP=/tmp
     ;;
   Windows_* )
     NULL=NUL
     PS=";"
     FS="\\"
     CP="cp -f"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized operating system!"
--- a/jdk/test/sun/security/tools/jarsigner/PercentSign.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/jarsigner/PercentSign.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -51,21 +51,18 @@
     PS=":"
     FS="/"
     CP="${FS}bin${FS}cp -f"
-    TMP=/tmp
     ;;
   CYGWIN* )
     NULL=/dev/null
     PS=";"
     FS="/"
     CP="cp -f"
-    TMP=/tmp
     ;;
   Windows_* )
     NULL=NUL
     PS=";"
     FS="\\"
     CP="cp -f"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized operating system!"
--- a/jdk/test/sun/security/tools/jarsigner/diffend.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/jarsigner/diffend.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -46,21 +46,18 @@
     PS=":"
     FS="/"
     CP="${FS}bin${FS}cp -f"
-    TMP=/tmp
     ;;
   CYGWIN* )
     NULL=/dev/null
     PS=";"
     FS="/"
     CP="cp -f"
-    TMP=/tmp
     ;;
   Windows_* )
     NULL=NUL
     PS=";"
     FS="\\"
     CP="cp -f"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized operating system!"
--- a/jdk/test/sun/security/tools/jarsigner/oldsig.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/jarsigner/oldsig.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -47,21 +47,18 @@
     PS=":"
     FS="/"
     CP="${FS}bin${FS}cp -f"
-    TMP=/tmp
     ;;
   CYGWIN* )
     NULL=/dev/null
     PS=";"
     FS="/"
     CP="cp -f"
-    TMP=/tmp
     ;;
   Windows_* )
     NULL=NUL
     PS=";"
     FS="\\"
     CP="cp -f"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized operating system!"
--- a/jdk/test/sun/security/tools/keytool/AltProviderPath.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/keytool/AltProviderPath.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -50,19 +50,16 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    TMP=/tmp
     ;;
   CYGWIN* )
     NULL=/dev/null
     PS=";"
     FS="/"
-    TMP=/tmp
     ;;
   Windows_* )
     NULL=NUL
     PS=";"
     FS="\\"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized operating system!"
--- a/jdk/test/sun/security/tools/keytool/SecretKeyKS.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/keytool/SecretKeyKS.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -49,19 +49,16 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    TMP=/tmp
     ;;
   CYGWIN* )
     NULL=/dev/null
     PS=";"
     FS="/"
-    TMP=/tmp
     ;;
   Windows_* )
     NULL=NUL
     PS=";"
     FS="\\"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized operating system!"
--- a/jdk/test/sun/security/tools/keytool/StandardAlgName.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/keytool/StandardAlgName.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -50,19 +50,16 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    TMP=/tmp
     ;;
   CYGWIN* )
     NULL=/dev/null
     PS=";"
     FS="/"
-    TMP=/tmp
     ;;
   Windows_* )
     NULL=NUL
     PS=";"
     FS="\\"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized operating system!"
--- a/jdk/test/sun/security/tools/keytool/i18n.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/keytool/i18n.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -50,19 +50,16 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    TMP=/tmp
     ;;
   CYGWIN* )
     NULL=/dev/null
     PS=";"
     FS="/"
-    TMP=/tmp
     ;;
   Windows* )
     NULL=NUL
     PS=";"
     FS="\\"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized system!"
--- a/jdk/test/sun/security/tools/keytool/resource.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/keytool/resource.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -46,17 +46,14 @@
   SunOS | Linux )
     NULL=/dev/null
     FS="/"
-    TMP=/tmp
     ;;
   CYGWIN* )
     NULL=/dev/null
     FS="/"
-    TMP=/tmp
     ;;
   Windows_* )
     NULL=NUL
     FS="\\"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized operating system!"
@@ -65,13 +62,11 @@
 esac
 
 # the test code
-${TESTJAVA}${FS}bin${FS}keytool > ${TMP}${FS}temp_file_40875602475 2> ${NULL}
-grep MissingResourceException ${TMP}${FS}temp_file_40875602475
+${TESTJAVA}${FS}bin${FS}keytool > temp_file_40875602475 2> ${NULL}
+grep MissingResourceException temp_file_40875602475
 
 if [ $? -eq 0 ]; then 
-    rm ${TMP}${FS}temp_file_40875602475
     exit 1
 fi
 
-rm ${TMP}${FS}temp_file_40875602475
 exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/keytool/trystore.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -0,0 +1,65 @@
+#
+# Copyright (c) 2011, 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 7047200
+# @summary keytool can try save to a byte array before overwrite the file
+
+if [ "${TESTJAVA}" = "" ] ; then
+  JAVAC_CMD=`which javac`
+  TESTJAVA=`dirname $JAVAC_CMD`/..
+fi
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+  Windows_* )
+    FS="\\"
+    ;;
+  * )
+    FS="/"
+    ;;
+esac
+
+rm trystore.jks 2> /dev/null
+
+KEYTOOL="${TESTJAVA}${FS}bin${FS}keytool -storetype jks -keystore trystore.jks"
+$KEYTOOL -genkeypair -alias a -dname CN=A -storepass changeit -keypass changeit
+$KEYTOOL -genkeypair -alias b -dname CN=B -storepass changeit -keypass changeit
+
+# We use -protected for JKS keystore. This is illegal so the command should
+# fail. Then we can check if the keystore is damaged.
+
+$KEYTOOL -genkeypair -protected -alias b -delete -debug
+
+if [ $? = 0 ]; then
+    echo "What? -protected works for JKS?"
+    exit 1
+fi
+
+$KEYTOOL -list -storepass changeit
+
+if [ $? != 0 ]; then
+    echo "Keystore file damaged"
+    exit 2
+fi
--- a/jdk/test/sun/security/tools/policytool/Alias.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/policytool/Alias.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -51,13 +51,11 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    TMP=/tmp
     ;;
   Windows* )
     NULL=NUL
     PS=";"
     FS="\\"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized system!"
--- a/jdk/test/sun/security/tools/policytool/ChangeUI.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/policytool/ChangeUI.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -50,13 +50,11 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    TMP=/tmp
     ;;
   Windows* )
     NULL=NUL
     PS=";"
     FS="\\"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized system!"
--- a/jdk/test/sun/security/tools/policytool/OpenPolicy.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/policytool/OpenPolicy.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -50,13 +50,11 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    TMP=/tmp
     ;;
   Windows* )
     NULL=NUL
     PS=";"
     FS="\\"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized system!"
--- a/jdk/test/sun/security/tools/policytool/SaveAs.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/policytool/SaveAs.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -51,13 +51,11 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    TMP=/tmp
     ;;
   Windows* )
     NULL=NUL
     PS=";"
     FS="\\"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized system!"
--- a/jdk/test/sun/security/tools/policytool/UpdatePermissions.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/policytool/UpdatePermissions.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -50,13 +50,11 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    TMP=/tmp
     ;;
   Windows* )
     NULL=NUL
     PS=";"
     FS="\\"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized system!"
--- a/jdk/test/sun/security/tools/policytool/UsePolicy.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/policytool/UsePolicy.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -50,13 +50,11 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    TMP=/tmp
     ;;
   Windows* )
     NULL=NUL
     PS=";"
     FS="\\"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized system!"
--- a/jdk/test/sun/security/tools/policytool/i18n.sh	Thu Sep 15 18:53:21 2011 -0700
+++ b/jdk/test/sun/security/tools/policytool/i18n.sh	Wed Jul 05 17:50:47 2017 +0200
@@ -50,13 +50,11 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    TMP=/tmp
     ;;
   Windows* )
     NULL=NUL
     PS=";"
     FS="\\"
-    TMP="c:/temp"
     ;;
   * )
     echo "Unrecognized system!"