Pain in mailinglist usage

I think using mailing-lists is really painful sometimes.

I thought about this multiple times sometime ago and now after I got two fresh examples(2nd) I think it is time to blog about.

So what causes my pain when I use mailing-lists?
It is not the fact to follow a discussion or writing to it.
It is the preferred way of using email for the synchronizing posts and threads.

Maybe the UseNet with its “out of fashion” NNTP-Protocol or even the “old” UUCP where better in at least one point: You can download the archive, contribute to discussions that are started long before your first subscription and always follow the thread-tree.

So what should we do? Switch back to Usenet with all out discussions? Which new tools we can use to manage discussions? What are the requirements for a good discussion toolchain?

Here are some requirements i see in first place.
1. Easy To Use (ok, email is a clear winner in this field)
2. Subscription-Phase (For me this is mostly :”registering for unmoderated posting”)
3. Spam-Prevention
a) through managing the Subscription-Phase with a moderator
b) through moderating Posts from users that
4. Keeping Discussions Thread (comprehensible Follow-Ups)

So what about git/mercurial or any other DVCS?
We got trees, predecessor objects and got superb synchronizing work-flows.
We can inject moderator-functions like in code-review systems.
We can label threads with tag-names(this can replace crosspostings).
We can use cryptography for authentication for registered users (like githubs)

Am i missing something? Why nobody has build this yet? Is there a good reason I don’t see, or haven’t I found it?

Comments are always welcome.


Remove Flaws in Java-APIs

I think i made a small step in a conzept how solutions that removes design flaws (such as public fields) can be solved in an binary compatible way. Public fields in public API are really nasty, and there isn’t a solution how this can be resolved without completely removing this class (with a long deprecation phase in the meantime). It is because the missing encapsulation for accessing this field gives you no change to change behavoir (such as checking/permitting values and state). It is this nasty (for public instance fields) GET_FIELD bytecode instruction.

It is like Dalibor Topic told it : “Breaking binary compatibility is bad, bad, really, really bad”

But than in saw a video on Virtual Extension Method with Brain Goetz which solves the compatibility problem introduced by extending the jdk for lambda expressions. After that i created a small concept-prototype which shows how it can work with simple bytecode transformations and invoke dynamic. I think there is much room for improvement and maybe it can be better implemented at the vm level, but actually i don’t have the knowledge to do so. And in special : “If you have a golden hammer,….” .

I placed the implementation of the concept on my github incubator

What is this doing?

1. The build.xml looks complicated but this is not the point here. It compiles the needed things to show the concept here. There is much room optimizing this, but i don’t do it because it is really unnecessary.

2. The Problem is the class OLD. It has a public field cause which can be access be anyone. If you put this in an public API you can never change/remove this field without breaking binary compatibility.

2.1. There is a class NEW which introduces the incompatibility in making the public field private. But is also introduces two methods that allows us to access the field in a controlled way.

2.2 There is a class NEW2 also which is nearer on my original problem (i tried to remove a public cause field in an exception-class in openjdk). It can throw an exception if changing the cause in the same manner java.lang.Throwable does it.

3. The Class GEN generates three testclasses (TestOld,TestNew and TestNew2) with the same testsequence with is like this:

OLD o = new OLD();
o.cause = new RuntimeException("NEW");

TestNew does it with NEW and TestNew2 does this with NEW2.
I have done it with class generating techniques because it would not compile and it would need a really complicated build-file to show how it works, so it was easier to generate some bytecode.

4. The Class Main does an overall test with the three testclasses TestOld, TestNew and TestNew2.

Executing the Main class without any additional processing is:

    [java] <<OLD>>
     [java] java.lang.RuntimeException: INIT_OLD
     [java] java.lang.RuntimeException: NEW
     [java] <<NEW>>
     [java] Exception in thread "main" java.lang.IllegalAccessError: tried to access field NEW.cause from class TestNew
     [java] 	at TestNew.testIt(TestNew.txt:3)
     [java] 	at Main.main(

The access of the cause field



The Test does not even reach the testcase TestNew2

But if you start the Main class with the jvmarg -javaagent:transformer.jar the output is

     [java] MOCKINJECT BCI
     [java] <<OLD>>
     [java] java.lang.RuntimeException: INIT_OLD
     [java] java.lang.RuntimeException: NEW
     [java] <<NEW>>
     [java] java.lang.RuntimeException: INIT_NEW
     [java] java.lang.RuntimeException: NEW
     [java] <<NEW2>>
     [java] java.lang.RuntimeException: INIT_NEW
     [java] ***java.lang.IllegalStateException: Not allowed to change

I think this is realy cool. The methods getCause() and initCause are used instead of the field in the cases where the field is not accessable.

4. How does this work?
The classes in the transformer.jar transforms the bytecode before loading into the vm.
It replaces the GET_FIELD / PUT_FIELD instruction with something like:

INVOKEDYNAMIC cause (LNEW;)Ljava/lang/Throwable; [Bootstrapper.getFunction(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; (6)]
INVOKEDYNAMIC cause (LNEW;Ljava/lang/Throwable;)V [Bootstrapper.setFunction(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; (6)]

You can look the complete bytecode of the testclases if you search for the .txt files in the tmp dir after executing the build script.
It invokes the bootstrap methods Bootstrapper.getFunction and Bootstrapper.setFunction in the Bootstrapper class.

5. The Bootstapper class connects the invokedynamic call with the field if accessable or with the accordant annotated access method getCause or initCause.

So what do you think? Please throw comments on me, also if you think binary compatible accessors for public fields is a really bad idea. I think there is much room for optimizations here, but first lets discuss about the idea and the conzept.

— Sebastian

Backward compatibility Object Serialization in Java

Breaking object-serialization in Java is easy. Just change some fields in the used DTOs transfered via network and whooopp its broken.

I came along this topic as i tried some openjdk contribution.

The contribution was to same exceptions that are extending RuntimeException but not supporting the 2 conventional constructors with the exception cause.

There are 10 Exception where i found a seperate cause field.

1. javax/xml/crypto/    private Throwable _exception;
2. javax/security/sasl/    private Throwable _exception;
3. java/lang/reflect/    private Throwable undeclaredThrowable;
4. java/lang/reflect/    private Throwable target;
5. java/lang/    private Throwable ex;
6. com/sun/java/browser/dom/    private Throwable ex;
7. com/sun/java/browser/dom/    private Throwable ex;
8. javax/naming/    protected Throwable rootException = null;
9. java/rmi/    public Throwable detail;
10. java/rmi/activation/    public Throwable detail;

Nr. 1 was the first i have looked at. My first attempt was to just remove the cause field add the missing constructors and remove the unnessacery methods for printing the stacktrace. But this definitly break serialisation compatibility. The serialversionUID is the same but the serialization content is missing the cause field.

My second attempt was to add the cause field in serialization manually through introducing something like this.

  65     private static final ObjectStreamField[] serialPersistentFields = {
  66         new ObjectStreamField("cause", Throwable.class)};
 114     private void readObject(ObjectInputStream stream)
 115             throws IOException, ClassNotFoundException {
 116         initCauseFieldFromSerializationStream(stream, "cause");
 117     }
 119     private void writeObject(ObjectOutputStream stream)
 120             throws IOException {
 121         writeCauseAsAPrivateField(stream, "cause");
 122     }

While introducing the following in

1097     protected void initCauseFieldFromSerializationStream(ObjectInputStream stream, String oldFieldName) throws ClassNotFoundException, IOException {
1098         GetField readFields = stream.readFields();
1099         Throwable cause = (Throwable) readFields.get(oldFieldName, this);
1100         /* If there is a cause that is deserialized and there is no cause
1101          * set in Throwable.cause (== null means serialized prior jdk8)
1102          * then initialize cause. There is another implicit functionality here:
1103          * If Throwable.cause is initialized yet(since jdk8) and
1104          * this.getCause() != cause then there is something is rotten in the
1105          * state of Denmark. Calling initCause in this situation will result
1106          * in an exception
1107          */
1108         if (cause != null && this.getCause() != cause) {
1109             // If cause is
1110             initCause(cause);
1111         }
1112     }
1131     protected void writeCauseAsAPrivateField(ObjectOutputStream stream, String oldFieldName) throws IOException {
1132         PutField putFields = stream.putFields();
1133         if (this.getCause() != null) {
1134             putFields.put(oldFieldName, this.cause);
1135         }
1136         stream.writeFields();
1137     }

This might be ok. But it is somewhat the otherway around this problem is solved already in
the other cases mentioned above. The other solution leaves the cause field but utilizes the
functionality of chaining in Throwable in an much easier fashion.

But this will be part of another post.

OpenJDK Contributions

After i have contributed to openjdk7 same time ago and followed the JAVA 7 Launch i decided to continue contributing to openjdk.

But where to start. I didn’t followed openjdk developement since my contribution. So i started reading the mailing-lists.

After some minor reviews and comments i started some small projects to start contributing code again.

  1. Chain Exceptions more consequently
  2. Reduce Warnings
  3. and maybe Iterable support for Enumerations

While Project 3 is not yet started. Project 1 and 2 are running.

Chain Exceptions more consequently

I started with InternalError because i found some amount of places where new InternalError().initCause(ex) is used instead of chaining rootcause via ctor-parameter. After i changed InternalError and it’s supertyp itself i changed the places where initCause where called. After that i searched for every instantiation of InternalError with the “old” ctors and looked if i can chain with some root-cause. This is not an really complex task but it takes some time to do it.

After that i started over with RuntimeException. Again search instantiation with the old ctors. Chain Exception where possible. Maybe i introduce some performance issues with this. But i don’t really think so.

While checking if all is compiling after my changes i ran into an problem with new warnings. But after some questions in the mailing list and a clean make it was gone. I checked if i introduce new warnings through my changes and found that there a some warnings in existing code that can be fixes without much effort.

Reduce Warnings

There where places where a varargs argument doen’t match Object[] or Object. Example: if you submit String[] to an vararg-argument you can some warnings, because the compiler can not figure out if you want to submit an simgle Object or if you want to submit various String to the varargs-argument. An cast to Object or Object[] does the trick.

The second warning type that can be fixed easily is unnecessary cast. Just remove the cast and it’s done.

How to submit to openjdk?

I created a free hosting account. And uploaded the webrevs to it. Here are my actual webrevs for openjdk

Contributions run running thought the mailing list with public review. I hope to get some good feedback.

On the road again

Welcome to my Weblog.

I the near future you will read at all i get along by my coding adventures.

Hope to have some news soon.

– CodingWizard