Re: java.util.Properties extending from HashMap<Object, Object> instead of HashMap<String, String>



On Sun, 06 Apr 2008 10:15:12 -0400, Lew <lew@xxxxxxxxxxxxx> wrote:

You proposed that to be "compatible" with pre-1.0 days, Hashtable and Dictionary would have to be implemented as having <Object, Object> parameters.

I made no such proposal: I merely followed your earlier line of reasoning to an outcome that was inconsistent.

At most it would have affected compile-time compatiblity.

Yes, that is the entire point. What is this "at most" stuff? That *is* the point.

I admit this could be the reason. But it seems highly unlikely. Sun has *never* guaranteed compile-time compatibility, and treats it only as a nicety. If we return to the example:

Object o="foo";
new Properties().put(o, "bar");

If properties were of type <String,String>, then this would generate a compile time warning, letting the programmer know they've done something in a way they are not supposed to. The source fix is completely trivial: change the first line to:

String o="foo";

Given the simplicity of the code fix, plus the ability to compile using "-source 1.4" until the source can be corrected, I would bet that Sun would consider the benefit of additional error checking to outweigh the inconvenience of source changes during the developer's transition to Java 5. This would also have made the put & putAll methods generate warnings when adding non-Strings, re-enforcing the discouraged practice of putting raw objects into these methods, which would have been a good thing.

Actually, you show a way to abuse Properties. You aren't supposed to use 'put()':
the put and putAll methods can be applied to a Properties object. Their use is strongly discouraged

You are spot-on here. As I was thinking about the more likely reason for Sun to do this, I came across something to point out. Properties has a subclass within the JDK: java.security.Provider. But look at the example usage of java.security.Provider:

http://java.sun.com/javase/6/docs/technotes/guides/security/crypto/HowToImplAProvider.html#AppA

public final class Sun extends Provider {
<snip>
public Sun() {
/* We are the SUN provider */
super("SUN", 1.2, INFO);
AccessController.doPrivileged(new java.security.PrivilegedAction() {
public Object run() {

/*
* Signature engines
*/
put("Signature.SHA1withDSA", "sun.security.provider.DSA");
<snip>
/*
* KeySize
*/
put("Signature.SHA1withDSA KeySize", "1024");
put("KeyPairGenerator.DSA KeySize", "1024");
put("AlgorithmParameterGenerator.DSA KeySize", "1024");

Ooooops. Sun violated their own convention, and used put instead of setProperty. Shame on them: I should probably file that.

Back to the original topic, I think I've figured out the reason!

Let's say a Java 1.4 developer copied the above code snippet. They may have carefully read the documentation for the Provider class, but not realized that the documentation in Properties makes use of non-string elements discouraged. In their initialization block, they simply write:

put("Signature.SHA1withDSA KeySize", new Integer(1024));

They hook in their provider, write their application, and since they don't use the load/store methods, everything runs just fine & dandy.

Now suppose Sun updates Properties to be of type <String,String>. The put method, at compile time, accepts only Strings. At runtime, two put methods are created, one for String,String, and one for Object,Object. Bridge methods are kind-of discussed in the JLS, Section 15.12.4.5, under the "Discussion" heading (if someone can find a better reference, please let me know)

http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.4.5

Anyway, it's obvious that one "put" method performs either up-casting or down-casting, and then acts as a bridge to the other. But, I can't find any evidence that the compiler will guarantee which method is the bridge, and which method does the work.

Key point: This implies that it is valid for javac to create an implementation of put(Object,Object) that casts it's parameters to Strings, and then acts as a bridge to put(String,String).

Since the Provider class does override put, if Properties were changed to <String,String>, then the put method in Provider would have to change signature to put(String,String) - I think this changes my "key point" from a possibility to a probability.

Now, Sun then publishes the JRE, and Properties.put(Object,Object) now casts it's parameters to Strings, and in turn calls put(String,String), since this is now legal.

Our end user then upgrades their JRE. Whoops. Suddenly, their app written by the Java 1.4 developer now fails: it throws some ClassCastExceptions and never runs. The end user switches back to Java 1.4 and everything runs fine again - maybe they can get an upgraded version from their developer, but they could just chalk it up as a Java bug.

Now this outcome strikes me as just the kind of deadly scenario Sun rigorously trys to avoid. Since Sun does try to ensure runtime compatibility such that a compiled binary will run on a newer JVM, this condition would probably constitute a Java bug.

So, please allow me to summarize the reasons that we've come up with so far:

* potential for runtime incompatibility when users put non-String entries into a Properties
* compile-time incompatibility when users use the discouraged methods put and putAll, even to store Strings
* pre-generics classes may be generified with an unbounded type, or with the bounded type Object, and not with any other bounded type
* making Properties expose Map methods was a mistake, which Sun is attempting to discourage
* Sun dropped the ball

I've ranked those in order of what strikes me as most probable reasons for Sun to choose to make Properties extend <Object,Object>.

If I have mis-interpretted your earlier posts, or if you have any other thoughts, I trust you'll respond!

-Zig
.



Relevant Pages

  • Re: Whither the large ENTER key?
    ... good reason for such a decision. ... And Sun does nothing of that? ... As a result Java remains Sun's semi-proprietary ... People are free to listen to or ignore my recommendations as they choose, ...
    (comp.sys.hp48)
  • Re: Any 3B1 alive?
    ... a Sun D-1000 JBOD full of SCA ... drives, and a Criiterion/EMC Fibre Channel JBOD full of FC drives where ... with blown power supply. ... It did compile on quite few obscure systems around ...
    (comp.sys.3b1)
  • MS JVM include insecure Sun classes?
    ... Did MS include any _Sun_ classes in their ... compile source/include classes Sun gave ... The reason I ask is that I am offering ... If _only_ MS classes are insecure, ...
    (comp.lang.java.programmer)
  • Re: Search For Solaris 10 / Sparc Development-Worskstatation
    ... LibMsgque-2.8 also doesn't compile out of the Box on Solaris 10 with ... the gcc compiler (solaris 10 ships with version 3.4.3), ... Big reason to consider Sun Studio for development on Solaris OS on ... As for GCC, Sun has also has married up the gcc front end with the ...
    (comp.unix.solaris)
  • Re: PPPoE DSL Solaris 10
    ... If you need DHCP then set things up that first. ... Left over from when Sun used to charge $$$ for a real C compiler ... so I cant compile rp-pppoe ... I can't say if DSL and PPPoE will work or not but the need to compile ...
    (comp.unix.solaris)