@@ -147,44 +147,7 @@ public abstract class Provider extends Properties {
147
147
148
148
private transient boolean initialized ;
149
149
150
- private static Object newInstanceUtil (final Class <?> clazz ,
151
- final Class <?> ctrParamClz , final Object ctorParamObj )
152
- throws Exception {
153
- if (ctrParamClz == null ) {
154
- Constructor <?> con = clazz .getConstructor ();
155
- return con .newInstance ();
156
- } else {
157
- // Looking for the constructor with a params first and fallback
158
- // to one without if not found. This is to support the enhanced
159
- // SecureRandom where both styles of constructors are supported.
160
- // Before jdk9, there was no params support (only getInstance(alg))
161
- // and an impl only had the params-less constructor. Since jdk9,
162
- // there is getInstance(alg,params) and an impl can contain
163
- // an Impl(params) constructor.
164
- try {
165
- Constructor <?> con = clazz .getConstructor (ctrParamClz );
166
- return con .newInstance (ctorParamObj );
167
- } catch (NoSuchMethodException nsme ) {
168
- // For pre-jdk9 SecureRandom implementations, they only
169
- // have params-less constructors which still works when
170
- // the input ctorParamObj is null.
171
- //
172
- // For other primitives using params, ctorParamObj should not
173
- // be null and nsme is thrown, just like before.
174
- if (ctorParamObj == null ) {
175
- try {
176
- Constructor <?> con = clazz .getConstructor ();
177
- return con .newInstance ();
178
- } catch (NoSuchMethodException nsme2 ) {
179
- nsme .addSuppressed (nsme2 );
180
- throw nsme ;
181
- }
182
- } else {
183
- throw nsme ;
184
- }
185
- }
186
- }
187
- }
150
+ private static final Object [] EMPTY = new Object [0 ];
188
151
189
152
private static double parseVersionStr (String s ) {
190
153
try {
@@ -1106,16 +1069,15 @@ private ServiceKey(String type, String algorithm, boolean intern) {
1106
1069
this .algorithm = intern ? algorithm .intern () : algorithm ;
1107
1070
}
1108
1071
public int hashCode () {
1109
- return Objects . hash ( type , algorithm );
1072
+ return type . hashCode () * 31 + algorithm . hashCode ( );
1110
1073
}
1111
1074
public boolean equals (Object obj ) {
1112
1075
if (this == obj ) {
1113
1076
return true ;
1114
1077
}
1115
- if (!(obj instanceof ServiceKey )) {
1078
+ if (!(obj instanceof ServiceKey other )) {
1116
1079
return false ;
1117
1080
}
1118
- ServiceKey other = (ServiceKey )obj ;
1119
1081
return this .type .equals (other .type )
1120
1082
&& this .algorithm .equals (other .algorithm );
1121
1083
}
@@ -1192,9 +1154,7 @@ private void parseLegacyPut(String name, String value) {
1192
1154
ServiceKey key = new ServiceKey (type , stdAlg , true );
1193
1155
Service s = legacyMap .get (key );
1194
1156
if (s == null ) {
1195
- s = new Service (this );
1196
- s .type = type ;
1197
- s .algorithm = stdAlg ;
1157
+ s = new Service (this , type , stdAlg );
1198
1158
legacyMap .put (key , s );
1199
1159
}
1200
1160
legacyMap .put (new ServiceKey (type , aliasAlg , true ), s );
@@ -1213,9 +1173,7 @@ private void parseLegacyPut(String name, String value) {
1213
1173
ServiceKey key = new ServiceKey (type , stdAlg , true );
1214
1174
Service s = legacyMap .get (key );
1215
1175
if (s == null ) {
1216
- s = new Service (this );
1217
- s .type = type ;
1218
- s .algorithm = stdAlg ;
1176
+ s = new Service (this , type , stdAlg );
1219
1177
legacyMap .put (key , s );
1220
1178
}
1221
1179
s .className = className ;
@@ -1238,9 +1196,7 @@ private void parseLegacyPut(String name, String value) {
1238
1196
ServiceKey key = new ServiceKey (type , stdAlg , true );
1239
1197
Service s = legacyMap .get (key );
1240
1198
if (s == null ) {
1241
- s = new Service (this );
1242
- s .type = type ;
1243
- s .algorithm = stdAlg ;
1199
+ s = new Service (this , type , stdAlg );
1244
1200
legacyMap .put (key , s );
1245
1201
}
1246
1202
s .addAttribute (attributeName , attributeValue );
@@ -1673,14 +1629,24 @@ private static String getEngineName(String s) {
1673
1629
* @since 1.5
1674
1630
*/
1675
1631
public static class Service {
1676
-
1677
- private String type , algorithm , className ;
1632
+ private final String type ;
1633
+ private final String algorithm ;
1634
+ private String className ;
1678
1635
private final Provider provider ;
1679
1636
private List <String > aliases ;
1680
1637
private Map <UString ,String > attributes ;
1638
+ private final EngineDescription engineDescription ;
1639
+
1640
+ // Reference to the cached implementation Class object.
1641
+ // Will be a Class if this service is loaded from the built-in
1642
+ // classloader (unloading not possible), otherwise a WeakReference to a
1643
+ // Class
1644
+ private Object classCache ;
1681
1645
1682
- // Reference to the cached implementation Class object
1683
- private volatile Reference <Class <?>> classRef ;
1646
+ // Will be a Constructor if this service is loaded from the built-in
1647
+ // classloader (unloading not possible), otherwise a WeakReference to
1648
+ // a Constructor
1649
+ private Object constructorCache ;
1684
1650
1685
1651
// flag indicating whether this service has its attributes for
1686
1652
// supportedKeyFormats or supportedKeyClasses set
@@ -1702,8 +1668,11 @@ public static class Service {
1702
1668
// this constructor and these methods are used for parsing
1703
1669
// the legacy string properties.
1704
1670
1705
- private Service (Provider provider ) {
1671
+ private Service (Provider provider , String type , String algorithm ) {
1706
1672
this .provider = provider ;
1673
+ this .type = type ;
1674
+ this .algorithm = algorithm ;
1675
+ engineDescription = knownEngines .get (type );
1707
1676
aliases = Collections .<String >emptyList ();
1708
1677
attributes = Collections .<UString ,String >emptyMap ();
1709
1678
}
@@ -1749,6 +1718,7 @@ public Service(Provider provider, String type, String algorithm,
1749
1718
}
1750
1719
this .provider = provider ;
1751
1720
this .type = getEngineName (type );
1721
+ engineDescription = knownEngines .get (type );
1752
1722
this .algorithm = algorithm ;
1753
1723
this .className = className ;
1754
1724
if (aliases == null ) {
@@ -1863,7 +1833,7 @@ public Object newInstance(Object constructorParameter)
1863
1833
}
1864
1834
Class <?> ctrParamClz ;
1865
1835
try {
1866
- EngineDescription cap = knownEngines . get ( type ) ;
1836
+ EngineDescription cap = engineDescription ;
1867
1837
if (cap == null ) {
1868
1838
// unknown engine type, use generic code
1869
1839
// this is the code path future for non-core
@@ -1890,7 +1860,7 @@ public Object newInstance(Object constructorParameter)
1890
1860
}
1891
1861
}
1892
1862
// constructorParameter can be null if not provided
1893
- return newInstanceUtil (getImplClass (), ctrParamClz , constructorParameter );
1863
+ return newInstanceUtil (ctrParamClz , constructorParameter );
1894
1864
} catch (NoSuchAlgorithmException e ) {
1895
1865
throw e ;
1896
1866
} catch (InvocationTargetException e ) {
@@ -1906,11 +1876,59 @@ public Object newInstance(Object constructorParameter)
1906
1876
}
1907
1877
}
1908
1878
1879
+ private Object newInstanceOf () throws Exception {
1880
+ Constructor <?> con = getDefaultConstructor ();
1881
+ return con .newInstance (EMPTY );
1882
+ }
1883
+
1884
+ private Object newInstanceUtil (Class <?> ctrParamClz , Object ctorParamObj )
1885
+ throws Exception
1886
+ {
1887
+ if (ctrParamClz == null ) {
1888
+ return newInstanceOf ();
1889
+ } else {
1890
+ // Looking for the constructor with a params first and fallback
1891
+ // to one without if not found. This is to support the enhanced
1892
+ // SecureRandom where both styles of constructors are supported.
1893
+ // Before jdk9, there was no params support (only getInstance(alg))
1894
+ // and an impl only had the params-less constructor. Since jdk9,
1895
+ // there is getInstance(alg,params) and an impl can contain
1896
+ // an Impl(params) constructor.
1897
+ try {
1898
+ Constructor <?> con = getImplClass ().getConstructor (ctrParamClz );
1899
+ return con .newInstance (ctorParamObj );
1900
+ } catch (NoSuchMethodException nsme ) {
1901
+ // For pre-jdk9 SecureRandom implementations, they only
1902
+ // have params-less constructors which still works when
1903
+ // the input ctorParamObj is null.
1904
+ //
1905
+ // For other primitives using params, ctorParamObj should not
1906
+ // be null and nsme is thrown, just like before.
1907
+ if (ctorParamObj == null ) {
1908
+ try {
1909
+ return newInstanceOf ();
1910
+ } catch (NoSuchMethodException nsme2 ) {
1911
+ nsme .addSuppressed (nsme2 );
1912
+ throw nsme ;
1913
+ }
1914
+ } else {
1915
+ throw nsme ;
1916
+ }
1917
+ }
1918
+ }
1919
+ }
1920
+
1909
1921
// return the implementation Class object for this service
1910
1922
private Class <?> getImplClass () throws NoSuchAlgorithmException {
1911
1923
try {
1912
- Reference <Class <?>> ref = classRef ;
1913
- Class <?> clazz = (ref == null ) ? null : ref .get ();
1924
+ Object cache = classCache ;
1925
+ if (cache instanceof Class <?> clazz ) {
1926
+ return clazz ;
1927
+ }
1928
+ Class <?> clazz = null ;
1929
+ if (cache instanceof WeakReference <?> ref ){
1930
+ clazz = (Class <?>)ref .get ();
1931
+ }
1914
1932
if (clazz == null ) {
1915
1933
ClassLoader cl = provider .getClass ().getClassLoader ();
1916
1934
if (cl == null ) {
@@ -1923,7 +1941,7 @@ private Class<?> getImplClass() throws NoSuchAlgorithmException {
1923
1941
("class configured for " + type + " (provider: " +
1924
1942
provider .getName () + ") is not public." );
1925
1943
}
1926
- classRef = new WeakReference <>(clazz );
1944
+ classCache = ( cl == null ) ? clazz : new WeakReference <Class <?> >(clazz );
1927
1945
}
1928
1946
return clazz ;
1929
1947
} catch (ClassNotFoundException e ) {
@@ -1933,6 +1951,26 @@ private Class<?> getImplClass() throws NoSuchAlgorithmException {
1933
1951
}
1934
1952
}
1935
1953
1954
+ private Constructor <?> getDefaultConstructor ()
1955
+ throws NoSuchAlgorithmException , NoSuchMethodException
1956
+ {
1957
+ Object cache = constructorCache ;
1958
+ if (cache instanceof Constructor <?> con ) {
1959
+ return con ;
1960
+ }
1961
+ Constructor <?> con = null ;
1962
+ if (cache instanceof WeakReference <?> ref ){
1963
+ con = (Constructor <?>)ref .get ();
1964
+ }
1965
+ if (con == null ) {
1966
+ Class <?> clazz = getImplClass ();
1967
+ con = clazz .getConstructor ();
1968
+ constructorCache = (clazz .getClassLoader () == null )
1969
+ ? con : new WeakReference <Constructor <?>>(con );
1970
+ }
1971
+ return con ;
1972
+ }
1973
+
1936
1974
/**
1937
1975
* Test whether this Service can use the specified parameter.
1938
1976
* Returns false if this service cannot use the parameter. Returns
@@ -1960,7 +1998,7 @@ private Class<?> getImplClass() throws NoSuchAlgorithmException {
1960
1998
* used with this type of service
1961
1999
*/
1962
2000
public boolean supportsParameter (Object parameter ) {
1963
- EngineDescription cap = knownEngines . get ( type ) ;
2001
+ EngineDescription cap = engineDescription ;
1964
2002
if (cap == null ) {
1965
2003
// unknown engine type, return true by default
1966
2004
return true ;
0 commit comments