68
Javaのバージョニング問題 の話しよっか 室星亮太 2016/01/21() 1回 ゆるゆる高専エンジニアLT大会 at FULLER

Javaのバージョニング問題の話しよっか

Embed Size (px)

Citation preview

Javaのバージョニング問題の話しよっか

室星亮太

2016/01/21(木)(第1回(ゆるゆる高専エンジニアLT大会(at(FULLER

突然ですが問題です

このクラスを含むライブラリがあります(core_v1.jar)

package com.mrstar.versioning_problem.core;

public final class Core { private Core() {}

public static String getTitle() { return "ほげふが";

}

public final static String MESSAGE = "ぴよぴよ!";}

さっきのライブラリに依存するライブラリがあります(framework.jar)

package com.mrstar.versioning_problem.framework;import com.mrstar.versioning_problem.core.Core;

public class Framework { private Framework(){ } public static void showTitle() { System.out.println(Core.getTitle()); } public static void showMessage() { System.out.println(Core.MESSAGE); }}

こんな感じで使います

package com.mrstar;import com.mrstar.versioning_problem.framework.Framework;

public class Main { public static void main(String[] args) { Framework.showTitle(); Framework.showMessage(); }}

実行すると...

package com.mrstar;import com.mrstar.versioning_problem.framework.Framework;

public class Main { public static void main(String[] args) { Framework.showTitle(); // 「ほげふが」って表示される Framework.showMessage(); // 「ぴよぴよ!」って表示される }}

こっからがポイントですもうちょっと状況説明が続きます

仮の文言を本番用に変更し、バージョンアップ(core_v2.jar)

package com.mrstar.versioning_problem.core;

public final class Core { private Core() {}

public static String getTitle() { return "メインページ"; // さっきまで「ほげふが」 } // さっきまで「ぴよぴよ!」 public final static String MESSAGE = "こんにちは!";

}

core_v2.jarに置き換えて、framework.jarはそのままで

package com.mrstar;import com.mrstar.versioning_problem.framework.Framework;

public class Main { public static void main(String[] args) { Framework.showTitle(); // Q1 なんて表示される? Framework.showMessage(); // Q2 なんて表示される? }}

Q1#「Framework.showTitle();」• 「ほげふが」って表示されると思う人?

• 「メインページ」って表示されると思う人?

Q2#「Framework.showMessage();」• 「ぴよぴよ!」って表示されると思う人?

• 「こんにちは!」って表示されると思う人?

答え合わせ!

Q1#Framework.showTitle()は「メインページ」って表示されます

 

Q2#Framework.showMessage()は「ぴよぴよ!」って表示されます

あってた?

解説!

framework.jarのFramework.java(再掲)

package com.mrstar.versioning_problem.framework;import com.mrstar.versioning_problem.core.Core;

public class Framework { private Framework(){ } public static void showTitle() { System.out.println(Core.getTitle()); } public static void showMessage() { System.out.println(Core.MESSAGE); }}

これをコンパイルした結果がポイント!

framework.jarの中身をデコンパイルすると...

デコンパイルしたFramework.class

package com.mrstar.versioning_problem.framework;import com.mrstar.versioning_problem.core.Core;

public class Framework { private Framework() {} public static void showTitle() { System.out.println(Core.getTitle()); } public static void showMessage() { System.out.println("ぴよぴよ!"); }}

気づいた?もう一回みてみましょう!

Framework.javaのコード

package com.mrstar.versioning_problem.framework;import com.mrstar.versioning_problem.core.Core;

public class Framework { private Framework(){ } public static void showTitle() { System.out.println(Core.getTitle()); } public static void showMessage() { System.out.println(Core.MESSAGE); }}

デコンパイルしたFramework.class

package com.mrstar.versioning_problem.framework;import com.mrstar.versioning_problem.core.Core;

public class Framework { private Framework() {} public static void showTitle() { System.out.println(Core.getTitle()); } public static void showMessage() { System.out.println("ぴよぴよ!"); }}

おわかりいただけましたか?

デコンパイルした.class

Core.MESSAGEの文字列リテラルの「ぴよぴよ」

直接埋め込まれていましたね!

Core.MESSAGEの文字列リテラル、直接埋め込まれていましたね!

public'sta+c'final'String'MESSAGE'(略)

直接埋め込まれていましたね!

バージョニング問題!用語自体はC#のもの

public'sta+c'final'intやpublic'sta+c'final'String

等クラス定数の箇所はコンパイルすると数値・文字列リテラルに展開されます!

framework.jarは

core_v1.jarに依存しビルドしました

その後、再ビルドしませんでしたね

framework.jarを再ビルドするまで、Framewarkクラス内の

Coreクラスの定数Core.MESSAGEを使っている箇所は

core_v1の「ぴよぴよ」のままです

想像してください!

製品版のプログラムでテスト用の文言が出てきてしまうのを!

((((;゚Д゚))))

まぁぶっちゃけピヨピヨ

とか、かわいいもんだよね(汗)

「ここに射幸心をジャブジャブ煽る文言」笑えないね

ポイントおさらい

public'sta+c'final'intみたいな定数は

コンパイルするとリテラルとして展開される

※プリミティブ型とString型

「framework.jar再ビルドすりゃよくね?」

まぁそうなんだけど、Java書くならこれは知っといてほしい

定数が埋め込まれて思わぬバグの原因になるから!

遅くなりましたが自己紹介

• 室星亮太

• 最初はJavaでAndroid+(2016年でもJava6+orz)

• 最近までC#でUnity+(2016年でもC#3.0(一部4.0)+orz)

• 今はTypeScriptでNode.js+(JavaScriptむずいね)

「バージョニング問題、稀なケースなんでしょ?」

わたしもそう思っていた時期がありました。

去年遭遇しましたUnity&+&Android&+&ある広告SDKで

またまた問題です!今度はAndroid経験者が対象

Androidでpublic,sta0c,final,int

なよく使うやつってな~んだ!?

Rクラス

R.layout.activity_mainのようなリソースID

レイアウトや画像に振られるリソースID(intな定数)

Rクラスのパッケージ名はアプリのパッケージ名に

RクラスのリソースID利用例

public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // これ!!!ビルドすると整数リテラルに setContentView(R.layout.activity_main); }}

Unity&+&Android&+&ある広告SDKで

バージョニング問題が原因の不具合に遭遇!

Unity+Android+ある広告SDKの構成例これはUnity4までのやり方で現在は非推奨

レイアウトのXMLや画像などのリソース上記リソースを使う広告表示機能のjar

(AndroidManifest.xml)

jarの中のクラスでは、R.layout.activity_main

みたいなリソースIDの定数、リテラルとして展開されてるよね!

Unityはビルド時、Androidのアプリを作るため

新たにAndroidプロジェクトを作って

このタイミングでリソースに再度リソースIDが振られます

jarの中のクラスでは、R.layout.activity_main

みたいなリソースIDの定数、リテラルとして展開されてるよね!

もし

プラグインが二つになったら

プラグインが二つになったら

この状態でAndroidプロジェクトを作りリソースIDを振り直したら

プラグインのJarの中の整数リテラルとUnityが新たに作るリソースIDの整数が

ずれる!

実行時エラー!

タチが悪い

public'sta+c'final'intがベタ書きされた

jarを作ったSDK開発者が悪い!

jarの中のリソースIDとUnityが作るAndroidプロジェクトのリソースIDとが一致しない!

最悪、非常にギルティ

さてさて、バージョニング問題

理解してもらえましたか?

みんなバージョニング問題を引き起こしそうなライブラリ作っちゃいけませんよ!

約束な!

Javaのバージョニング問題の話しよっか 

室星亮太

2016/01/21(木)(第1回(ゆるゆる高専エンジニアLT大会(at(FULLER