Sunday, March 10, 2013

Major Countries Military Action Principle

Found from a Chinese version:
1,美国,想打谁就打谁;
2,英国,美国打谁我打谁;
3,俄罗斯,谁骂我我打谁;
4,日本,谁打我我让美国打谁;
5,朝鲜,谁让我不痛快我就打韩国;
 6,韩国,谁打我我和美国一块军演吓唬谁;
7,中国,谁打我我就骂谁。

 Translate to English:
1. US, I will beat whoever I want.
2. UK, I will beat whoever US wants to beat.
3. Russia, I will beat whoever condemns me.
4. Japan, I will let US beat whoever beats me.
 5. North Korea, I will beat South Korea if anyone makes me unhappy.
6. South Korea, I will have military exercises with US whenever someone beats me.
7. China, I will condemn whoever beats me.

Thursday, March 7, 2013

How does IncompatibleClassChangeError happen (with sample code)



Introduction

When different teams working separately producing libraries consumed by each other ,you may run into a problem with the java.lang.IncompatibleClassChangeError exception.

What does this exception mean?

IncompatibleClassChangeError means the class in the classloader is not the same format as the one compiled. (class vs interface)

How does this happened?


E.G.  
  • Your application "app" with dependency jar b in class path.
  • A is your code in app which has a reference with class B and compiled with b.
  • The class B in b-beta version was refactored to an interface
  • When you run your application, the code is running and load your dependency with b-beta.
  • Since the B as an interface not same as the one compiled as a class. Bang!~ The application throws the exception.

Sample code with Maven



I made an example to demonstrate how this happened. The code sample can be found here:
https://github.com/datianshi/maven-inCompatibleClassChangeError

The five repos are: version1, version2, framework1, framework2, app

You can run maven clean install with the above sequences in your local box

Version 1 and Version2 have the same group id and artifact id, while the version is not the same (Here in order to simulate multiple version with different code locally, I created two repo for the same group and artifact). version1 has an interface Person, while version2 has a class Person.

Framework1 depends on version1 Person, while Framework2 depends on version2 Person.

The app depends on both framework1 and framework2. When maven loads the dependencies, it has to resolve the conflicts for version1 and version2, because they are having the same artifact and group. Maven uses "nearest win" policy to resolve the conflicts, then version1 wins.

When the app loads Framework2, it was looking for class Person, but the classloader contains an interface Person. The application failed like below.

mvn exec: java inside of app folder.


Caused by: java.lang.IncompatibleClassChangeError: Found interface org.freelance.incomp.core.Person, but class was expected
at org.freelance.version2.SayPerson.sayPerson(SayPerson.java:9)
at org.freelance.incomp.app.App.main(App.java:12)