ko.utils(配列編)
これはKnockoutJSアドベントカレンダーの記事です。
KnockoutJS Advent Calendar 2014 - Qiita
今日は Knockout の便利機能が入った ko.utils について適当に紹介します。
今回は配列編。
紹介するのは以下のメソッドです。
- ko.utils.arrayForEach
- ko.utils.arrayFirst
- ko.utils.arrayFilter
- ko.utils.arrayGetDistinctValues
- ko.utils.arrayMap
- ko.utils.arrayPushAll
- ko.utils.arrayRemoveItem
ちなみにソースコードはここです。
https://github.com/knockout/knockout/blob/master/src/utils.js
- ko.utils.arrayForEach
配列をぐるぐるします。
サンプル
var years = [1950, 1960, 1970, 1980]; ko.utils.arrayForEach(years, function(item, index){ console.log(index + " : " + item); });
結果
0 : 1950 1 : 1960 2 : 1970 3 : 1980
- ko.utils.arrayFirst
配列の中で最初に条件に一致した値を返します。
サンプル
var strArray = ["a1", "b2", "c3", "d4"]; var result = ko.utils.arrayFirst(strArray, function(value){ return value.charAt(0) === "b"}); console.log(result);
結果
b2
- ko.utils.arrayFilter
配列を指定した条件でフィルタした結果の配列を返します。
サンプル
var result = ko.utils.arrayFilter(["a", "b", "c", "d", "e", "f"], function (item, index) { return index % 2 == 0; }); console.log(result);
結果
["a", "c", "e"]
- ko.utils.arrayGetDistinctValues
配列の中の重複しない値を返します。
var result = ko.utils.arrayGetDistinctValues(["a", "b", "b", "c", "c"]); console.log(result);
結果
["a", "b", "c"]
- ko.utils.arrayIndexOf
最初に見つかった配列の値のインデックスを返します。
見つからなかった場合は -1 を返します。
var result1 = ko.utils.arrayIndexOf(["a", "b", "c", "d", "c"], "c"); console.log(result1); var result2 = ko.utils.arrayIndexOf(["a", "b", "c"], "d"); console.log(result2);
結果
2 -1
- ko.utils.arrayMap
配列の中の各要素に対して特定の処理を行った配列を返します。
var result = ko.utils.arrayMap([1, 2, 3, 4, 5], function(item, index){ return item * 2; }); console.log(result);
結果
[2, 4, 6, 8, 10]
- ko.utils.arrayPushAll
配列に他の配列を追加します。
サンプル
var targetArray = [1,2,3]; var extraArray = ["a", "b", "c"]; ko.utils.arrayPushAll(targetArray, extraArray); console.log(targetArray);
結果
[1, 2, 3, "a", "b", "c"]
- ko.utils.arrayRemoveItem
最初に一致した値を配列から削除します。(一つだけ)
サンプル
var input = ["a", "b", "c", "b", "e"]; ko.utils.arrayRemoveItem(input, "b"); console.log(input);
結果
["a", "c", "b", "e"]
ここのブログと内容がかぶったけどCoffeeではなくJavaScriptで書いたのでご愛嬌。
http://weathercook.hatenadiary.jp/entry/2013/01/06/211720
ko.computedとko.pureComputed
これはKnockoutJSアドベントカレンダー5日目の記事です。
KnockoutJS Advent Calendar 2014 - Qiita
依存性の追跡(トラッキング)は ko.observable / ko.observableArray と ko.computed の組み合わせで行います。
例えば、生まれた年(西暦)から現在の年齢を算出するのをKnockoutを使って書くと次のようになります。
<p>Enter your birth year: <input data-bind='value: birthYear' maxlength="4"/></p> <p>You're <strong data-bind='text: age'></strong> years old.</p> <script> function ViewModel() { var self = this; self.birthYear = ko.observable(); self.age = ko.computed(function(){ var now = new Date(); var age = now.getFullYear() - parseInt(self.birthYear()); if(isNaN(age)) return 0; return age; }); } ko.applyBindings(new ViewModel()); </script>
- (値が変わらなくても)常に通知するようにしたり、一定時間経ってから通知したりする
上記のサンプルにあるように ko.computed の中で呼ばれる ko.observable / ko.observableArray の値が変わると ko.computed が呼ばれます。
逆にいうと値が変わらないと通知されないのですが、これを常に通知するように簡単に拡張できます。
myViewModel.fullName = ko.pureComputed(function() { return myViewModel.firstName() + " " + myViewModel.lastName(); }).extend({ notify: 'always' });
上記のように computed に .extend({ notify: 'always'}) をつけるだけです。
この書き方は extender と呼ばれ、 notify 以外にも rateLimit extender があります。
これは通知されるまでに設定された時間分待ってから通知します。
これは KnockoutJS 3.1.0 で追加されたのでそれ以前のバージョンでは throttle という名前でした(若干動きが違いますが・・・)
また、この extender は簡単に拡張できるのでドキュメントや実際のプロジェクトとか見てみると参考になるかと思います。
ドキュメント
Knockout : Using extenders to augment observables
実際のプロジェクト
knockout.persist/knockout.persist.js at master · spoike/knockout.persist · GitHub
- peek を使ってトラッキングを制御する
もし computed 内で呼び出している observable A と observable B のうち、
observable A が変更したときだけ computed を実行して、observable B が変更されても computed が実行されない場合はどうしたらよいでしょうか。
これをするには computed 内の observable B に peek() を最後に追加するだけで実現できます。
- ko.pureComputed とは何か
ko.pureComputed は Knockout 3.2.0 で追加されました。
公式サイトによるとこの機能を使うことにより以下の点で改善があるようです。
1. メモリーリークを防ぐ
2. 計算のオーバーヘッドを防ぐ
これはHTMLに現在バインディングされていない(アクティブでない) pureComputed は実行されないということです。
公式ドキュメントのサンプルがよくできているのでこれを使って説明します。
http://knockoutjs.com/documentation/computed-pure.html
<div class="log" data-bind="text: computedLog"></div> <!--ko if: step() == 0--> <p>First name: <input data-bind="textInput: firstName" /></p> <!--/ko--> <!--ko if: step() == 1--> <p>Last name: <input data-bind="textInput: lastName" /></p> <!--/ko--> <!--ko if: step() == 2--> <div>Prefix: <select data-bind="value: prefix, options: ['Mr.', 'Ms.','Mrs.','Dr.']"></select></div> <h2>Hello, <span data-bind="text: fullName"> </span>!</h2> <!--/ko--> <p><button type="button" data-bind="click: next">Next</button></p>
function AppData() { this.firstName = ko.observable('John'); this.lastName = ko.observable('Burns'); this.prefix = ko.observable('Dr.'); this.computedLog = ko.observable('Log: '); this.fullName = ko.pureComputed(function () { var value = this.prefix() + " " + this.firstName() + " " + this.lastName(); // Normally, you should avoid writing to observables within a pure computed // observable (avoiding side effects). But this example is meant to demonstrate // its internal workings, and writing a log is a good way to do so. this.computedLog(this.computedLog.peek() + value + '; '); return value; }, this); this.step = ko.observable(0); this.next = function () { this.step(this.step() === 2 ? 0 : this.step()+1); }; }; ko.applyBindings(new AppData());
このサンプルでは表示するHTMLをNextボタンを押す度に次のステップになり、ステップ0〜2 の 3回に分けて表示しています。
ステップ0では First name の入力、ステップ1では Last name の入力、ステップ2では Prefix の入力と fullName の表示を行っています。
ここで注目すべきところは、fullName が ko.pureComputed で定義されていることです。
fullNameの中では First name, Last name, Prefix を呼び出しているにも関わらず、fullName が実行されるのは
fullNameが実際にバインドされる「ステップ2」の段階になったときです。
今まで使っていた ko.computed だとどのステップにも関わらず実行されていたものを、ちゃんと「今つかっているか」を判断し、計算してくれます。
ko.pureComputed はComponentsを使った大規模なSPAでは、特に必要になってくるため地味な機能に見えて大変重要な機能ではないのかと思っています。
実際にサンプルも今まで ko.computed で書いてあったところを ko.pureComputed で書き直していたりしているので、
これからは ko.computed よりも ko.pureComputed を使った方が良い気がします。
逆に ko.computed を使う場面としては公式ドキュメントには以下のように書いてあります。
Knockout : Pure computed observables
1. 複数の observable に影響があるコールバックを ko.computed で使う場合
ko.computed(function () { var cleanData = ko.toJS(this); myDataClient.update(cleanData); }, this);
2. バインディングの init メソッドで要素を更新するために ko.computed を使う場合
ko.computed({ read: function () { element.title = ko.unwrap(valueAccessor()); }, disposeWhenNodeIsRemoved: element });
用途として基本的には pureComputedを使い、初期値やサーバサイドで値が変わったら常に実行したい場合は ko.computed を使う感じなのかなと思います。
明日は @yusuke_nozoe さんです!よろしくお願いします!
Components を使ってみる
これはKnockoutJSアドベントカレンダー3日目の記事です。
KnockoutJS Advent Calendar 2014 - Qiita
KnockoutJS 3.2では新しく Components という機能が追加されました。
作者のブログにもあるようにこの機能は web components に強く影響された機能で、コンポーネント単位で非同期にページをレンダリングします。
Componentsを使うとどのように書くことができるのか見てみましょう。
まず普通のKnockoutで書いたサンプルです。
<html lang="ja"> <html> <head> <title> Component Examples</title> <script src="knockout-3.2.0.js"></script> </head> <body> <p>Enter your name: <input data-bind='value: name'/></p> <p>You entered <strong data-bind='text: name().toUpperCase()'></strong></p> <script> var viewModel = { name: ko.observable('something') }; ko.applyBindings(viewModel); </script> </body> </html>
デモはこちら。
このデモを全く同じ動作のまま Components を使って書くと以下のようになります。
<!DOCTYPE html> <html lang="ja"> <head> <title> Component Example </title> <script src="js/knockout-3.2.0.js"></script> </head> <body> <name-editor></name-editor> <script> ko.components.register('name-editor', { template: "<p>Enter your name: <input data-bind='value: name'/></p><p>You entered <strong data-bind='text: name().toUpperCase()'></strong></p>", viewModel: function() { this.name = ko.observable('something'); } }); ko.applyBindings(); </script> </body> </html>
このデモはこちら。
まったく同じ動作ですが、ko.components.register を使い "name-editor" という名前のComponentを登録しています。
これによりコンポーネントの再利用することが可能になります。
またコンポーネントは作成するときに以下のようにパラメータを渡してやることができます。
KnockoutJSのComponentsでは "component"バインディングも用意されており、他のバインディングと同じように data-bind でコンポーネントを指定することもできます。
デモはこちら。
<!DOCTYPE html> <html lang="ja"> <head> <title> Component Example </title> <script src="js/knockout-3.2.0.js"></script> </head> <body> <name-editor params="value: 'hello world'"></name-editor> <div data-bind="component: { name: 'name-editor', params: { value: 'hoge bar' } }"></div> <script> ko.components.register('name-editor', { template: "<p>Enter your name: <input data-bind='value: name'/></p><p>You entered <strong data-bind='text: name().toUpperCase()'></strong></p>", viewModel: function(params) { this.name = ko.observable(params.value); } }); ko.applyBindings(); </script> </body> </html>
いかがでしたでしょうか。
ざっと軽く見ただけでも便利なのが分かってもらえるかと思います。
さらに、KnockoutJSはこの機能もIE6のような古いブラウザーでも動くように実装しているらしいですが未検証です。
明日は @sukobuto さんの 「THETA BINDING」 です!よろしくお願いします!
JVM仕様にあるクラスファイルのフォーマットについて
これはJVMアドベントカレンダー1日目の記事です。
JVM Advent Calendar 2014 - Qiita
JVM仕様にあるクラスファイルのフォーマットについて書きます。
JavaのクラスファイルのフォーマットはJVM仕様の4章で定義されています。
Chapter 4. The class File Format
ClassFile { u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; }
全く分からない状態からこれらのフォーマットについてひとつづつ読んでいくのは辛いと思うのでざっくり説明します。
クラスファイルが必要なので適当なJavaのソースコードを作ってコンパイルします。
class AdventCalendar2014 { public static void main(String[] args) { System.out.println("Hello JVM Advent Calendar 2014!"); } }
% javac AdventCalendar2014.java % ls AdventCalendar2014.class AdventCalendar2014.java
クラスファイルが出来たので今度はバイナリを覗いてみましょう。
以前そういうやつ書いたことがあるのでこれを使うことにします。
これをそのままコピってきてコンパイルしてさっきのクラスファイルを引数に指定すると、
2進数と16進数でクラスファイルの中身を出力します。
% java ClassReader /path/to/AdventCalendar2014.class Binary |Hex ------------ 11001010 CA 11111110 FE 10111010 BA 10111110 BE 00000000 0 00000000 0 00000000 0 00110100 34 00000000 0 00011101 1D 00001010 A 00000000 0 00000110 6 00000000 0 00001111 F 00001001 9 00000000 0 00010000 10 00000000 0 00010001 11 00001000 8 00000000 0 00010010 12 00001010 A 00000000 0 00010011 13 00000000 0 00010100 14 00000111 7 00000000 0 00010101 15 00000111 7 00000000 0 00010110 16 00000001 1 00000000 0 00000110 6 00111100 3C 01101001 69 01101110 6E 01101001 69 01110100 74 00111110 3E ・・・
2進数は読みにくいので16進数だけにしたら以下のような感じになりました。
CAFEBABE00000034001D0A0006000F09001000110800120A001300140700150700160100063C696E 69743E010003282956010004436F646501000F4C696E654E756D6265725461626C650100046D6169 6E010016285B4C6A6176612F6C616E672F537472696E673B295601000A536F7572636546696C6501 0017416476656E7443616C656E646172323031342E6A6176610C000700080700170C001800190100 1F48656C6C6F204A564D20416476656E742043616C656E64617220323031342107001A0C001B001C 010012416476656E7443616C656E646172323031340100106A6176612F6C616E672F4F626A656374 0100106A6176612F6C616E672F53797374656D0100036F75740100154C6A6176612F696F2F507269 6E7453747265616D3B0100136A6176612F696F2F5072696E7453747265616D0100077072696E746C 6E010015284C6A6176612F6C616E672F537472696E673B2956002000050006000000000002000000 070008000100090000001D00010001000000052AB70001B100000001000A00000006000100000002 0009000B000C00010009000000250002000100000009B200021203B60004B100000001000A000000 0A000200000005000800060001000D00000002000E
これを最初のJVM仕様のクラスフォーマットと照らし合わせていきましょう。
magic っていうのはマジックナンバーでJavaクラスの先頭はこの値が入ります。
これは Cafe(C++, A Front End)というC++コンパイラのプロダクトマネージャの Kim Polese さんの愛称(babe)からきているというのがまことしやかに噂として流れています。
CA FE BA BE // u4 magic; 00 00 // u2 minor_version; 00 34 // u2 major_version; 00 1D // u2 constant_pool_count;
ってみていくと cp_info っていうよく分からないのが登場しました。
これもJVM仕様読んでいくと 4.4 で以下のように定義されています。
cp_info { u1 tag; u1 info[]; }
一番最初の tag でデータの種類を定義していて、その値によって次の info[] の読み方が変わります。
例えば tag = 7 の場合は CONSTANT_Class なので、その場合は CONSTANT_Class_info を読みます。
というような感じで進めていくと以下のようになります。
CA FE BA BE // u4 magic 00 00 // u2 minor_version = 0 00 34 // u2 major_version = 57 00 1D // u2 constant_pool_count = 29 // cp_info #1 0A // tag = 10 (CONSTANT_Methodref) 00 06 // u2 class_index = 6 00 0F // u2 name_and_type_index = 15 // cp_info #2 09 // tag = 9 (CONSTANT_Fieldref) 00 10 // u2 class_index = #16 00 11 // u2 name_and_type_index = #17 // cp_info #3 08 // tag = 8 (CONSTANT_String) 00 12 // u2 string_index = #18 // cp_info #4 0A // tag = 10 (CONSTANT_Methodref) 00 13 // u2 class_index = #19 00 14 // u2 name_and_type_index = #20 // cp_info #5 07 // tag = 7 (CONSTANT_Class) 00 15 // u2 name_index = #21 // cp_info #6 07 // tag = 7 (CONSTANT_Class) 00 16 // u2 name_index = #18 // cp_info #7 01 // u1 tag = 1 (CONSTANT_Utf8) 00 06 // u2 length = 6 3C 69 6E 69 74 // u1 bytes[length] = <init> 3E // cp_info #8 01 // u1 tag = 1 (CONSTANT_Utf8) 00 03 // u2 length = 3 28 29 56 // u1 bytes[length] = ()V // cp_info #9 01 // u1 tag = 1 (CONSTANT_Utf8) 00 04 // u2 length = 4 43 6F 64 65 // u1 bytes[length] = Code // cp_info #10 01 // u1 tag = 1 (CONSTANT_Utf8) 00 0F // u2 length = 15 4C 69 6E 65 4E // u1 bytes[length] = LineNumberTable 75 6D 62 65 72 54 61 62 6C 65 // cp_info #11 01 // u1 tag = 1 (CONSTANT_Utf8) 00 04 // u2 length = 4 6D 61 69 6E // u1 bytes[length] = main // cp_info #12 01 // u1 tag = 1 (CONSTANT_Utf8) 00 16 // u2 length = 22 28 5B 4C 6A 61 // u1 bytes[length] = ([Ljava/lang/String;)V 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 // cp_info #13 01 // u1 tag = 1 (CONSTANT_Utf8) 00 0A // u2 length = 10 53 6F 75 72 63 // u1 bytes[length] = SourceFile 65 46 69 6C 65 // cp_info #14 01 // u1 tag = 1 (CONSTANT_Utf8) 00 17 // u2 length = 23 41 64 76 65 6E // u1 bytes[length] = AdventCalendar2014.java 74 43 61 6C 65 6E 64 61 72 32 30 31 34 2E 6A 61 76 61 // cp_info #15 0C // u1 tag = 12 (CONSTANT_NameAndType) 00 07 // u2 name_index = #7 00 08 // u2 descriptor_index = #8 // cp_info #16 07 // tag = 7 (CONSTANT_Class) 00 17 // u2 name_index = #23 0C // u1 tag = 12 (CONSTANT_NameAndType) 00 18 // u2 name_index = #24 00 19 // u2 descriptor_index = #25 ・・・
まぁあとは同じです。。
なんと驚くべきことに、ここまですべて手作業で解析してきましたが、さすがにもうしんどいです。
Javaチョットデキル人はご存知の人も多いですが、この解析は javap すれば簡単に出力してくれます。
% javap -c -verbose AdventCalendar2014 Classfile /path/to/AdventCalendar2014.class Last modified 2014/11/30; size 461 bytes MD5 checksum 94ccbcbc2ad1fdedf9c05cf088ca89f5 Compiled from "AdventCalendar2014.java" class AdventCalendar2014 minor version: 0 major version: 52 flags: ACC_SUPER Constant pool: #1 = Methodref #6.#15 // java/lang/Object."<init>":()V #2 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream; #3 = String #18 // Hello JVM Advent Calendar 2014! #4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V #5 = Class #21 // AdventCalendar2014 #6 = Class #22 // java/lang/Object #7 = Utf8 <init> #8 = Utf8 ()V #9 = Utf8 Code #10 = Utf8 LineNumberTable #11 = Utf8 main #12 = Utf8 ([Ljava/lang/String;)V #13 = Utf8 SourceFile #14 = Utf8 AdventCalendar2014.java #15 = NameAndType #7:#8 // "<init>":()V #16 = Class #23 // java/lang/System #17 = NameAndType #24:#25 // out:Ljava/io/PrintStream; #18 = Utf8 Hello JVM Advent Calendar 2014! #19 = Class #26 // java/io/PrintStream #20 = NameAndType #27:#28 // println:(Ljava/lang/String;)V #21 = Utf8 AdventCalendar2014 #22 = Utf8 java/lang/Object #23 = Utf8 java/lang/System #24 = Utf8 out #25 = Utf8 Ljava/io/PrintStream; #26 = Utf8 java/io/PrintStream #27 = Utf8 println #28 = Utf8 (Ljava/lang/String;)V { AdventCalendar2014(); descriptor: ()V flags: Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 2: 0 public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String Hello JVM Advent Calendar 2014! 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return LineNumberTable: line 5: 0 line 6: 8 } SourceFile: "AdventCalendar2014.java"
こんな感じです。
明日は @sugarlife さんの「OpenJDKのソースコード配置(1-2サブディレクトリ程度まで)」です!
よろしくお願いします!
KnockoutJSの紹介
これはKnockoutJSアドベントカレンダー1日目の記事です。
KnockoutJS Advent Calendar 2014 - Qiita
一発目なので最初は KnockoutJS とはどんなものなのかについて書きたいと思います。
KnockoutJSとはMVVMパターンでJavaScriptで作る動的なUIをシンプルに構築するライブラリです。
※個人的にはフレームワークではなくライブラリだと思っている
公式サイトには以下のような標語で書かれています。
Simplify dynamic JavaScript UIs with the Model-View-View Model (MVVM)
KnokoutJSを一言でいえば、「バインディングフレームワーク」の一種です。
以下の特徴があります。
・他のライブラリ(jQueryなど)に依存しない
・IE 6+, Firefox 3.5+, Chrome, Opera, Safari など比較的古いブラウザに対応している
個人的にKnockoutJSが好きな箇所としては主に以下の2点です。
(1) 余計な機能があまりない(学習コストが高くない)
(2)(前述の特徴にもあるように)古いブラウザに対応している
まず、(1)ですが、KnockoutJSでは「data-bind=""」って空でタイプすることができれば7割ぐらいKnockoutをマスターしたものだと思ってもらっても過言ではないです。
3.1までは・・・。
それほどまでに余分な機能は削ぎ落されていてはいるものの、拡張性も高く様々なプラグインも用意されています。
Plugins · knockout/knockout Wiki · GitHub
プラグインは上記ページだけではなく、他にも
SteveSanderson/knockout.mapping · GitHub
SteveSanderson/knockout-projections · GitHub
SteveSanderson/knockout-es5 · GitHub
などといったKnockoutJS作者本人が作ったプラグインも数多くあるので見てみるのもいいと思います。
knockout-mappingについてはまた後日説明しようと思います。
(2) については KnockoutJSはVue.jsとは違い、レガシー・ブラウザもサポートしています。
その代わりVue.jsほどスタイリッシュではないし色々内部で泥臭いこともやっているのですが、現実解として古いブラウザーもサポートしないといけない場面は実際の仕事ではよくあることなのではないでしょうか?
というわけで明日は @hakurai さんです!たぶん Haxe について書いてくれると思います!
OpenJDKをビルドしてみた
環境はMac。
基本ソースをMercurialでクローンしてREADME読めばできる。
READMEにもあるけど、詳しいビルド方法はここを参照すればいい。
http://hg.openjdk.java.net/jdk8/jdk8/raw-file/tip/README-builds.html
以下、作業手順。
デバッグ版が欲しい場合は Configure時に--enable-debug するとよい。
% hg clone http://hg.openjdk.java.net/jdk8/jdk8 jdk8_src requesting all changes adding changesets adding manifests adding file changes added 942 changesets with 1309 changes to 136 files updating to branch default 82 files updated, 0 files merged, 0 files removed, 0 files unresolved % cd jdk8_src % ./get_source.sh # Repositories: corba jaxp jaxws langtools jdk hotspot nashorn corba: hg clone http://hg.openjdk.java.net/jdk8/jdk8/corba corba jaxp: hg clone http://hg.openjdk.java.net/jdk8/jdk8/jaxp jaxp jaxp: requesting all changes corba: requesting all changes corba: adding changesets jaxp: adding changesets Waiting 5 secs before spawning next background command. jaxp: adding manifests corba: adding manifests jaxws: hg clone http://hg.openjdk.java.net/jdk8/jdk8/jaxws jaxws langtools: hg clone http://hg.openjdk.java.net/jdk8/jdk8/langtools langtools jaxws: requesting all changes langtools: requesting all changes jaxws: adding changesets langtools: adding changesets 〜 中略 〜 .: cd . && hg pull -u ./corba: cd ./corba && hg pull -u ./hotspot: cd ./hotspot && hg pull -u ./jaxp: cd ./jaxp && hg pull -u ./jaxws: cd ./jaxws && hg pull -u ./jdk: cd ./jdk && hg pull -u ./langtools: cd ./langtools && hg pull -u ./nashorn: cd ./nashorn && hg pull -u ./hotspot: pulling from http://hg.openjdk.java.net/jdk8/jdk8/hotspot ./nashorn: pulling from http://hg.openjdk.java.net/jdk8/jdk8/nashorn ./jaxws: pulling from http://hg.openjdk.java.net/jdk8/jdk8/jaxws ./jaxp: pulling from http://hg.openjdk.java.net/jdk8/jdk8/jaxp ./langtools: pulling from http://hg.openjdk.java.net/jdk8/jdk8/langtools .: pulling from http://hg.openjdk.java.net/jdk8/jdk8 ./corba: pulling from http://hg.openjdk.java.net/jdk8/jdk8/corba ./jdk: pulling from http://hg.openjdk.java.net/jdk8/jdk8/jdk ./hotspot: searching for changes ./hotspot: no changes found ./jaxws: searching for changes ./jaxws: no changes found ./jaxp: searching for changes ./jaxp: no changes found ./nashorn: searching for changes ./nashorn: no changes found ./langtools: searching for changes ./langtools: no changes found ./corba: searching for changes ./corba: no changes found .: searching for changes .: no changes found ./jdk: searching for changes ./jdk: no changes found % bash ./configure --enable-debug --with-target-bits=64 Running generated-configure.sh configure: Configuration created at Sat Oct 4 01:07:52 JST 2014. configure: configure script generated at timestamp 1389186094. checking for basename... /usr/bin/basename checking for bash... /bin/bash checking for cat... /bin/cat checking for chmod... /bin/chmod checking for cmp... /usr/bin/cmp 〜 中略 〜 checking if build directory is on local disk... yes configure: creating /Users/plugram/Desktop/jvm/jdk8_src/build/macosx-x86_64-normal-server-fastdebug/config.status config.status: creating /Users/plugram/Desktop/jvm/jdk8_src/build/macosx-x86_64-normal-server-fastdebug/spec.gmk config.status: creating /Users/plugram/Desktop/jvm/jdk8_src/build/macosx-x86_64-normal-server-fastdebug/hotspot-spec.gmk config.status: creating /Users/plugram/Desktop/jvm/jdk8_src/build/macosx-x86_64-normal-server-fastdebug/bootcycle-spec.gmk config.status: creating /Users/plugram/Desktop/jvm/jdk8_src/build/macosx-x86_64-normal-server-fastdebug/compare.sh config.status: creating /Users/plugram/Desktop/jvm/jdk8_src/build/macosx-x86_64-normal-server-fastdebug/spec.sh config.status: creating /Users/plugram/Desktop/jvm/jdk8_src/build/macosx-x86_64-normal-server-fastdebug/Makefile config.status: creating /Users/plugram/Desktop/jvm/jdk8_src/build/macosx-x86_64-normal-server-fastdebug/config.h ==================================================== A new configuration has been successfully created in /Users/plugram/Desktop/jvm/jdk8_src/build/macosx-x86_64-normal-server-fastdebug using configure arguments '--enable-debug --with-target-bits=64'. Configuration summary: * Debug level: fastdebug * JDK variant: normal * JVM variants: server * OpenJDK target: OS: macosx, CPU architecture: x86, address length: 64 Tools summary: * Boot JDK: java version "1.8.0_20" Java(TM) SE Runtime Environment (build 1.8.0_20-b26) Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode) (at /Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home) * C Compiler: i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build) version 2335.15.00) (at /usr/llvm-gcc-4.2/bin/llvm-gcc-4.2) * C++ Compiler: i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build) version 2335.15.00) (at /usr/llvm-gcc-4.2/bin/llvm-g++-4.2) Build performance summary: * Cores to use: 2 * Memory limit: 4096 MB * ccache status: not installed (consider installing) Build performance tip: ccache gives a tremendous speedup for C++ recompilations. You do not have ccache installed. Try installing it. % make all Building OpenJDK for target 'all' in configuration 'macosx-x86_64-normal-server-fastdebug' ## Starting langtools Compiling 2 files for BUILD_TOOLS Compiling 31 properties into resource bundles Compiling 777 files for BUILD_BOOTSTRAP_LANGTOOLS Creating langtools/dist/bootstrap/lib/javac.jar Updating langtools/dist/lib/src.zip Compiling 780 files for BUILD_FULL_JAVAC Creating langtools/dist/lib/classes.jar ## Finished langtools (build time 00:01:02) ## Starting hotspot make[2]: warning: -jN forced in submake: disabling jobserver mode. INFO: ENABLE_FULL_DEBUG_SYMBOLS=1 INFO: ENABLE_FULL_DEBUG_SYMBOLS=1 INFO: ENABLE_FULL_DEBUG_SYMBOLS=1 INFO: ENABLE_FULL_DEBUG_SYMBOLS=1 INFO: ENABLE_FULL_DEBUG_SYMBOLS=1 Creating Makefile ... Creating directory list ../shared_dirs.lst Creating flags.make ... Creating flags_vm.make ... Creating vm.make ... Creating adlc.make ... Creating jvmti.make ... Creating trace.make ... Creating sa.make ... Creating dtrace.make ... INFO: ENABLE_FULL_DEBUG_SYMBOLS=1 Creating Makefile ... Creating flags.make ... Creating flags_vm.make ... Creating vm.make ... Creating adlc.make ... Creating jvmti.make ... Creating trace.make ... 〜 中略 〜 ## Finished docs (build time 00:03:48) ----- Build times ------- Start 2014-10-04 01:10:54 End 2014-10-04 01:39:25 00:00:50 corba 00:01:00 demos 00:03:48 docs 00:12:07 hotspot 00:01:27 images 00:00:30 jaxp 00:00:44 jaxws 00:06:44 jdk 00:01:02 langtools 00:00:18 nashorn 00:28:31 TOTAL ------------------------- Finished building OpenJDK for target 'all' % make install Building OpenJDK for target 'install' in configuration 'macosx-x86_64-normal-server-fastdebug' ## Starting langtools ## Finished langtools (build time 00:00:01) ## Starting hotspot ## Finished hotspot (build time 00:00:00) ## Starting corba ## Finished corba (build time 00:00:00) ## Starting jaxp ## Finished jaxp (build time 00:00:01) ## Starting jaxws ## Finished jaxws (build time 00:00:00) ## Starting jdk ## Finished jdk (build time 00:00:03) ## Starting demos ## Finished demos (build time 00:00:00) ## Starting nashorn ## Finished nashorn (build time 00:00:00) ## Starting images Copying images/j2re-bundle/jre1.8.0.jre/Contents/Home/release Copying images/j2sdk-bundle/jdk1.8.0.jdk/Contents/Home/.DS_Store Copying images/j2sdk-bundle/jdk1.8.0.jdk/Contents/Home/jre Copying images/j2sdk-bundle/jdk1.8.0.jdk/Contents/Home/jre/.DS_Store Copying images/j2sdk-bundle/jdk1.8.0.jdk/Contents/Home/release ## Finished images (build time 00:00:04) ## Starting install Installing jdk image into /usr/local/jvm/openjdk-1.8.0-internal-fastdebug and creating 40 links from /usr/local/bin into the jdk. ## Finished install (build time 00:00:04) ----- Build times ------- Start 2014-10-04 01:54:51 End 2014-10-04 01:55:04 00:00:00 corba 00:00:00 demos 00:00:00 hotspot 00:00:04 images 00:00:04 install 00:00:01 jaxp 00:00:00 jaxws 00:00:03 jdk 00:00:01 langtools 00:00:00 nashorn 00:00:13 TOTAL -------------------------
インストールしたら /usr/local/bin に入った。
さっそく実験。
以下のようなソースを書いて実行。
class Hello { public static void main(String[] args) { new Hello().hello(); } public int hello() { int result = 1 + 2; return result; } }
% /usr/local/bin/javac Hello.java % /usr/local/bin/java -client -Xcomp -XX:+PrintIRWithLIR -XX:CompileOnly="Hello.hello" Hello __bci__use__tid____instr____________________________________ . 0 0 4 B1 [0, 0] -> B2 sux: B2 label [label:0xec065838] . 0 0 7 std entry B2 std_entry move [rsi|L] [R177|L] move [metadata:0xa1684420|M] [R178|M] move [Base:[R178|M] Disp: 108|I] [R179|I] add [R179|I] [int:8|I] [R179|I] move [R179|I] [Base:[R178|M] Disp: 108|I] move [metadata:0xa16842f0|M] [R180|M] logic_and [R179|I] [int:0|I] [R179|I] cmp [R179|I] [int:0|I] branch [EQ] [CounterOverflowStub: 0xec067718] label [label:0xec067740] branch [AL] [B2] __bci__use__tid____instr____________________________________ . 0 0 5 B2 (S) [0, 0] -> B0 dom B1 sux: B0 pred: B1 label [label:0xec065b48] . 0 0 6 goto B0 branch [AL] [B0] __bci__use__tid____instr____________________________________ . 0 0 0 B0 (SV) [0, 3] dom B2 pred: B2 label [label:0xec064e38] . 3 0 i3 ireturn i2 move [int:3|I] [rax|I] return [rax|I] __bci__use__tid____instr____________________________________ . 0 0 4 B1 [0, 0] -> B0 sux: B0 label [label:0xec8a8a38] . 0 0 5 std entry B0 std_entry move [rsi|L] [R177|L] branch [AL] [B0] __bci__use__tid____instr____________________________________ . 0 0 0 B0 (SV) [0, 3] dom B1 pred: B1 label [label:0xec8a8038] . 3 0 i3 ireturn i2 move [int:3|I] [rax|I] return [rax|I]
とりあえず今日はここまで。
友達から「これ無料で作ってよ」って言われたときに注意したいこと
最近あまりにもひどいので、今後同じような経験をしないよう備忘録として書いておきます。
プログラマとかデザイナーの人は一度は必ず経験があると思うのですが、
友人から「こんなアイデアがあるんだけど」「うちの会社のサイトがダサくてね」という切り出しで、
「"ちょっと"やってくれない?」って頼まれることがあります。
この"ちょっと"が曲者で、
・"ちょっと" だからお金を払わなくていいよね?
・"ちょっと" だからまた頼むね
って感じで友人という立場上、依頼者は頼みやすいので
最初は自分も特に嫌ではなく、やってしまうことがあります。
ですが、この次の "ちょっと" を "何となく" やってしまったため、
次もまた次も頼まれることになります。
こうなってくると、最初は無料で感謝してた友人の依頼者も
なぜか「当たり前にやってくれる」ものとして依頼してきて、
こちらがやりたいと思わないことも要求してきます。
こういうパターンを何回か経験しているので、いい加減自分も学習しろと思うのですが、
こうなってくるともう相手は自分のやりたいと思っていることも聞いてくれず、
また自分的にも単なる作業にしかならない仕事を休日を使ってやることになります。
土日作業し休みを費やしてやっても感謝されず(実際はありがとうの一言ぐらいは言ってもらえる)
一文も儲からないし技術的にもやりたいこととは違うので、やりたくないと思い始めるのですが、
問題はここで「やめる」といっても、依頼者は自分にはできないので「困る」としか言えません。
なので、とりあえず引き継ぐ方向性を探るのですが、そもそも無料でこんなことやりたい人なんかいないので、もちろん誰も見つかりません。
こうなってくるとその友人に会うのすら苦痛になり、友人関係も崩壊します。
そんな経緯が度々あったので、今後誰に頼まれても「無料で」なにかのアプリとかサイトを作るつもりは一切ありません。
勉強会で発表するのは続けたいですが、あくまで「自分がやりたいこと」と「終了期限や終了条件」が明確であることが前提です。
たぶん同じような状況になったことのある人も結構いると思うし、
現在こんな感じの状況の人も結構いると思う。
なのでそういう状況でいま困っている人は最初に「無料」でやる仕事の「終了条件」を
必ず依頼者と合意しておくことをお勧めします。
あと、アプリやサイトを無料で依頼してる人は「タダより高いものはない」ということ、
「アプリを作る」「サイトを運営する」には一定以上の覚悟と投資がないとできないと思っておいたほうがよいと思います。