婚活と一年振り返り
この記事はpyspa Advent Calendar 2021 - Adventarの二日目です。
去年の12月から今日この日までの一年は色々あり過ぎたので、ネタにするのは次の機会に回しつつ総括だけ記すと、「できるかぎり丁寧に、誠実に仕事を重ねて行けば、まわりまわって身を助けることもある」でした。今後ともご贔屓によろしくお願い申し上げます。
さて、去年婚活した結果、無事に結婚しました。
双方の両親には「婚活アプリで出会い」としっかり明朗に紹介して貰いました。そのおかげか何度か(パートナーが)ご相談を受けることもあったので、QA形式でこんな感じで男は動いているんだなというのを紹介していこうと思います。ただし、私の体験なので全員がそういうわけではありません。「こういうやつも居る」に留めて読んでいただけると幸いです。というわけで二年連続婚活ネタです。
前提
- 男
- 悪条件が多い: バツイチ、婚活では高年齢、難聴者
- 年齢以外の諸条件(外見・学歴・職業)は可もなく不可もなし
- 結婚願望がある
- 遊びは考えていない(年齢的にちんたら関係を続ける気がない)
どのサービスを使う?
- 複数同時並行が大前提
- 料金が男女で不公平かどうかは度外視(それで何が変わるのかを考えるより複数同時にやりゃ良い)
- DAIGOを広告塔に使っている某サービスなど、広告をどの対象に打っているかを元に取捨選択する
- 取捨選択が面倒なら結婚相談所に全部ぶん投げてやって貰うでも良さそう
サービス詳細
- Tinder、タップル
- 気軽にできるが怪しい人も多そう。とにかく手っ取り早く色んな人と会いたいならこれ。ということは結婚前提且つ若くない私には合わない。が、プロフィールの反応を見るのには良さそうなので一旦登録。でもよく考えたらこのサービスは無料でかつプロフィールを他サービスでも見て不信感持たれるのでは?? -> 退会
- Omiai、ゼクシィ恋結び、with
- withは趣味とか性格診断をしてくれるから楽しみながらできそう、でもDAIGOじゃん。使った感じ、(少なくとも自分が使っている期間は)ここら辺は広告頑張ってる割に母数が少ない
- 東京カレンダー
- なんか女性が判を押したかのように濃い。退会。
- 多分男側も濃そうだな
- ゼクシィ縁結び
- 男女とも月額を採るので多少は本気の人が多く、結婚相談所にも登録してそうな印象。ただし母数は少ない。
- Pairs
- 自分は最終的にここで出会った。周りもこれで結婚してるのが最多。色々バランスが良い。結局、恋愛サービスって自分がある程度信用している友人からのお勧めで利用している人が多いので、人が人を呼び話題に挙がりやすいのを選んだほうが良いという身も蓋もない結果に。
- 結婚相談所
- 去年の記事参照。自分には合わなさそうだったので一旦保留した。
プロフィールはどうした?
- 写真
- 仕事モードのきりっとした顔+全身が写っているやつを選んだ
- 友人らと過ごしてるリラックスモードのやつを選んだ
- 顔や髪、体系はどのみち直ぐ分かるので最初から見れるようにした
- 一応加工はしてない(会ったらなんか違うで時間を無駄にするのは無意味)
- 特に趣味らしい趣味はないので自分が写ってないのは載せない
- よくあるお高い食事とか料理を上げるのも考えたが、それに惹かれる方は結婚願望が高いというよりは逆じゃないかと考えて止めた
- 料理は茶色いので普通に写真映えしないから辞めた
- プロフィール内容
- 難聴以外の悪条件は全部載せた(後で見せてそれでNGだと時間が無駄になるので無意味)
- 難聴は誰なのか一気に絞れるので一見さんには開示してない
- 業種と年収は正直に書いた
- 生活レベルはそんなに高くないことも書きつつ、こうありたいという家族像も軽く書いた
いいねされた時にやったこと
プロフィールがちゃんとしているか、写真がちゃんとしているか、友人がいるか。どっかの仏像をプロフィールにしてないか
話題はどうしてる?
- いいねされた人から話して貰った話題をベースに広げたものをストックして使い回す
- 並行でやってるとどうしても話題は尽きるので使い回す
- 一回目までは出身や仕事、趣味や食事などの馬が合うかどうか、二回目までは主なお金の使い道や生活パターンなどもう少し込み入った話、三回目以降は流れで
職業や所属はどのタイミングで言うの?
やばい人に所属を具体的に言うと自分の想像を軽く上回る被害を受ける可能性があるので、ある程度の素性が知れない限りは業界レベルしか言わない。 ここでいう素性とは、「金回りがクリーン」「思想が偏ってない」「会話が通じる」の三点です。なので必然的に二回目に会った途中からある程度具体的に言います
医者だと言われたんだけど
年収2000万って言われたんだけど
- 役職持ちならGoogleで検索すれば出てくるのでは
- IT業界ならLinkedInや名刺SNS (https://8card.net/)で検索しよう
- 8cardはIT業界以外でも使っている人は居るかも
- それぐらいの年収の人は居るかもだが、想像できないなら多分自分と合ってない人なのでスルー
他の付き合いをやめるのはどのタイミング?
- あっマジで結婚前提で付き合う気だなと解った瞬間にサービスは利用しなくなった
- 実際にサービスを全部退会したのは同棲を決めたタイミング
- サービスは利用費が前払い制でかつ返ってこないので退会のタイミングはシビア
どれぐらいやりとりして会うの?
- 相手から言われない限りはだいたい6~10往復(一日1-3やり取りなので大体一週間)
- 最速4往復(向こうから提案され、凄い話が早く、かつ高速で切り上げられた)
- 最長二か月(結局この最長のやり取りをした人と付き合ってゴール)
- 大抵のサービスでは男女比がアンバランスなので、双方共に疲れて適当にご飯いかねとかになりがちかもしれないが、個人的には結婚前提だったのである程度馬が合いそうな人以外は会うだけ無駄なのでその手は採らなかった
どこで会うの?
- 昼でも夜でも良いが夕方のような半端な時間は避けた
- 夕方に来る人昼と夜にもスケジュール入れててサンドイッチ状態になり結果印象が薄くなるイメージがある
- 店はお勧めを聞いたり提案したりその時その時にあわせるがアレルギーや苦手なものは聞いた
- お酒はあまり気にしない
- 気にはしないが、自分が好きな物が相手も好きだと良いよね
- それで合わなかったらどうせ付き合っても続かないの気持ちで
- というわけでお気に入りのお店は並列していくつか持っていた
結局は最初から夜に会って新規のお店で日本酒をかぱかぱ飲んでた人がパートナーになったので運
まとめ
結局は数をこなした上での運なので偉そうなことはとても言えないが、自暴自棄になっても身に返るだけなので、「適度に気を配りつつ適度に気にしない」を自分なりに掴んで礼を失しない程度に並列で数をこなしたのが良かったかなと考えている。
色々あった一年だったが、何よりもパートナーに恵まれ、よりもっと遠くに行けそうだという実感があるのは最上の幸運だと思う。皆様のご健康とご多幸をお祈り申し上げます。次の一年もどうぞよろしくお願い致します。
婚活
この記事は pyspa Advent Calendar 202013日目です。
色々あったので婚活しました。
目標
さて、まずは目標を決めましょう。
- 時間を共にしてお互いに居心地が良いパートナーを見つける
相手側の私に求めるパートナー像は分からないので、ここでは自分のパートナーに求める像を具体化していきます
- 金銭感覚
- 余暇の過ごし方(時間の使い方)
- (自分自身の)不機嫌に対する対処方法
- 親戚付き合い
私はこの辺を具体化しました。
出会い系サービスを探す
次にサービスを見つけて行きましょう。友人の経験を聞いたり色々サービスを探したら広告が出会い系まみれになるので適当に見ていきます。
- Pairs
- Zexy 縁結び
- Omiai
- with
- 東カレデート
とりあえずこの辺から始めました。(大体半年か1年契約)
サービスを使う
人間、結果が見えないとやる気に繋がりません。が、男女比が非対称なので基本的に女性と男性のサービスに対するUXがかなり違います。
- 女性はすさまじい数いいね・メッセージを受け取る
- 見てる人は見てるだろうがそんなに見ない(そんな時間はない)
- 何か嫌なポイントがあれば簡単にやり取りは途絶える
というのを前提に当たって砕けろの方針でサービスを使っていきました。躓きポイントと改善ステップは以下のような感じです。
- いいねされない
- 気にしない
- 次ステップでのフィードバックに利用する
- いいねした後にマッチング(いいねが返ってくる)率が低い
- プロフィールに対するフィードバックとして利用
- やり過ぎない程度に一週間ごとに変えて改善したか見る
- このため「いいね」するペースは基本的に変えない。有料だと毎月追加されるサービスが多いのでそれを4で割る
- マッチング後に連絡が途絶える時がたまにある
- 大体1割ぐらいが終息不明になる
- なんか気になるポイントがあって気分で途絶えたと考えよう(一割は許容範囲と考えて改善しなかった)
- マッチング後に会うアポイントメントを取るまでの期間が長い
- 人によるが一週間もかからない程度に短縮していった
- 会話ネタを考えるのが面倒くさい
- サービスのシステム直接入力をやめてテキストに書くことで蓄積&パターン化して短縮した
- 一回会ってから二回目に行く率が低い
- 低い……
- 人によるとしか言いようがないやつ
- とりあえず行き先のストックを増やすことで二回目の予定を柔軟に入れれるようにした。行き先のストックはメッセージのやり取りで仕入れた
最終的に「アポイントとって一回会った数」を最大化していく戦略で改善していきました。それを繰り返していくにつれ1-4の部分が面倒くさくなってきたので結婚相談所に話を聞きに行きました。
結婚相談所サービス
上の通り、サービスを使った結論として「数を増やす」が絶対条件でした。これが可能かどうかの観点も含めて話を聞きに行きました
日本結婚相談所連盟(IBJ)
- 各地にある結婚相談所を登録窓口としたマッチングサービス。
- 登録料、成婚退会料がある
- まーお高い。(イニシャル1x万、ランニング1.x万、成婚退会料2x万)
- マッチング申請(お見合い申込)回数が月ごとに上限がある
- それとは別に紹介回数が月ごとに上限がある
- さらにそれとは別に面談が月か年ごとに上限がある
- 面談と担当者とのお見合いの状況共有は別
- ここらへんは結婚相談所に強く依存する。各所がそれぞれのサービスを提供している
- 基本はマッチングサービス。結婚相談所ごとの差異はサービスの内容
- 基本システムはIBJのシステムを使うってだけで普通の出会い系サービスとは大きな違いはない
- 写真はみんな写真館で撮るなどで気合い入れてる
- ↑写真を含め一般的なお見合いのマナーの指導が入る(これは結婚相談所の性質による)
- お気に入りシステムがあるが自分につく担当者と、お気に入り先の担当者にこの情報が見れる。担当者さん的には20個ぐらいお気に入りをつけて欲しい
- 上のお気に入り情報をもとに担当者間でやり取りがあってお見合いに結びつくこともある
- 基本、みんな新着順でみてるのでマッチング確度は3ヶ月も経つと落ちる。ここは一般的なマッチングサービスと一緒。
- 基本システムでマッチングが成立したら担当者を通じてお見合い設定が行われる(自分でしなくていい)
- 最近はオンラインお見合いもある。それでもOKかどうかの確認をされた(先方に担当者からお伝えする必要があるため)
- 会場は色々あるがホテルのラウンジだとか
- お見合い翌日の一時ぐらいまでに感触を伝える必要がある(システム的にはもっと遅くていいけどこの結婚相談所or担当者的にはそうらしい)。これで両方OKが出たら次の機会に進む
- この時の聞き取りとかは面談の回数とは別。面談は直接来訪(またはビデオ会議)して状況を聞いたり悩み事を相談したりする回。
- 並列して進めるのも勿論可能というか推奨されているが、だいたい一週間ごとに感触はどうか聞いてくるので答える
- 進めている相手の情報を聞くこともできる。
- 年収だとか聞きにくい(聞かないほうが良い)情報は(女性側は年収証明なしで年収を記載できるししなくても良い。また契約状況にも依るのであまり積極的に年収は基本聞かないほうが良いとか云々)聞くことが可能。そういった情報をもとに紹介のリコメンド精度を上げていく
- 逆に相手に自分の評判・特徴を伝えてくれることもある
- 他、ヒアリングシートを埋め、幾つか個人情報(離婚歴、原因、再婚を目指した理由、家族構成など)や、相手への要望をお伝えした利用すべきかどうかの観点
- 何度も言うが基本はIBJの高級マッチングサービス。登録されている情報にリーチでき、かつ、担当者が確度の高いリコメンドを提供してくれるのが価値である
- 登録されている人らの「本気度」と担当者との相性がすべてな状況でもある
- マッチングサービスの申し込み回数は限定されているがお気に入り回数は無制限。最初のヒアリングレポートとこのお気に入り情報をもとにリコメンドしてくれる(と思われる)
- 「システムに登録されている女性を1000人以上確認してお気に入りを100人くらいつけておいたので、相手側が入力済みで自分が見えないけどシステムユーザなら見える情報を使って、マッチング確度の高い順に並べ替えて下さい。そのリストの上から順に申し込みをします。」ということができると良い
- 見えない情報とは、「他のマッチングサービスを併用しているのが基本だと思われるので、併用していないユーザを優先度上げる」、とか。「相手が希望している年齢層や年収幅とマッチしている」、とか
- とはいえ完全にマッチングしていないところも含めてやらないと相手は見つからないので臨機応変ではあるが、それ込みで担当者の感性頼りも含めてリストができると一番いい
- これ以外に、個人的に価値があると考えるのは、1回目の会話が結構厳しいのでその補助(相手はどんな人だよと伝えてもらう)と良くなかったポイントを聞いてもらう(全部を改善するつもりはないが振る舞いは変えれる)というところ
- ただし、良くなかったポイントは基本的に当事者は無難に口を濁すであろうし、先方の担当者も私の担当者も更に丸めるだろうからそこまで有意義な価値にはならない可能性がある
- 服装だとか一般的な指導は入ると考えられる
まとめ
こんな感じで婚活をやっています。結果はコロナが落ち着いたころに or オンライン飲み会にて!
Java 14とJava 15の新機能解説 (LINE Developer Meetup #65 原稿)
Java 14とJava 15の新機能についてJJUG CCC 2020 Springで話す予定だった内容が中止になり、Java 15のリリースも近づいてきたので新たに資料を加筆修正して以下のLINE Developer Meetupで発表しました!
本イベントでは話す予定ではない部分も(JJUG CCCで話す予定だったので)資料にはあり、オンラインでの発表だったということもあり原稿も準備していました。そこで折角ですので情報保障を兼ねて共有したいと思います。情報保障についてはこちらを見てみてください。
なお、今回はかなり特殊な事例であり、基本的には原稿が公開されるケースは少ないと考えています。LINE Developer Meetupでは他の分野でもスライドに書かれていない内容を聞くことができるので、ぜひイベントを聴講してみてください :)
なお、スライドは以下から確認できます。また、スライドおよび原稿は元々markdownで記載しているため、はてな記法ではそのまま表示されています。
www.slideshare.net
ではお楽しみください:)
LINEでソフトウェアエンジニアとして働いている久保田祐史と言います。現在は全社的なKafkaのプラットフォームを提供しているチームで働いています。
(ここからは端折る)
これまでの仕事上、JVMのトラブルシューティングに関わることが多かったため、過去にはOpenJDKやicedteaへのコードのコントリビューションだとか、JavaOneでのプレゼンテーションをしてきました。
またJava(JDK) Flight RecordのOSS化で役目をある程度果たしてしまいましたが、HeapStatsというJVMのGCやクラス参照情報やヒープ情報の収集、そしてリアルタイムデッドロック検知等を行う、トラブルシューティングツールの開発も行っていました
私はよくJJUG CCCという国内のJavaのカンファレンスでGCやJVMに関するセッションの他に、専らJavaの新機能について紹介することが多いのですが、今日も同じようにJava 14とJava 15で利用可能な新機能と変更点を紹介していきたいと思います。
新機能を中心に話すので非互換性については今回は話しません。
注意事項として、本資料は [`jdk.java.net`](http://jdk.java.net) からダウンロードできる`JDK 14.0.2` および`JDK 15 (build 32)`で極力動作確認していますが、全ての確認はできていませんのでコードを修正する前に動作確認してください
実装は各Javaのアップデートリポジトリ(http://hg.openjdk.java.net/jdk-updates/jdk14u/、http://hg.openjdk.java.net/jdk-updates/jdk15u/)、そして最新リポジトリ(http://hg.openjdk.java.net/jdk/jdk)で確認しています
さて、それでは見ていきましょう。
Java 14と15ではこのような数だけ変更がありました。
Java Enhancement Proposals、JEPは新機能レベルの変更、Compatibility and Specification Reviewsは非互換性を伴う変更です。
これ以外にバグ修正も行われていますが、基本的にバージョンアップ時でしか行われない変更はこの2つです。
ただし最近はバックポートという形で新機能レベルの追加がマイナーバージョンアップデートで行われることがあります。つい先日JDK Flight RecorderがJava 8に導入されたのもバックポートの一つです。
いずれにせよバージョンアップデートが半年ごとになりましたが、アップデートの数は今でもあまり変わらず多い状態です。
先程言いました通り、今回は新機能について話しますので、ここでは追加されたJEPを紹介していきます。
まずはじめに言語レベルやAPIレベルの変更について紹介していきます。Java 14も15もこの変更が最も多数を占めています。
ここからは新機能を一つずつ説明していきます。
パターンマッチングがJava 14からプレビュー機能として導入されました。なおここで言う「パターンマッチ」は正規表現のではなく、オブジェクトの型、つまりクラスです。
今まではBeforeで示されている通り `instanceOf` で型を比較してからわざわざキャストする必要がありましたが、今後はAfterで示されている通りキャストする必要なくそのままダイレクトに処理を書くことができます。意外に細かい修正ですが、これによってコードがスッキリすることで読みやすさやメンテナンスのしやすさが想像以上に改善されました。
将来的には switch 文でも同じように記載できるようにすることが展望としてありますが、現在のところはドラフト状態でまだ時期も内容も定まっていません。
Java 15では変更なしでSecond Previewとなっています。通例的には大きな問題がなければ次のJava 16で標準機能となる予定です。
(注意)上のスライドの下部コードは「どのようなフィールドやメソッドが生えるか」のイメージ図を記載していたため明記していませんでしたが、クラス宣言は以下のようにするのがより正確です。
public final class TestRecord(String s, int i) extends java.lang.Record {
(注意ここまで)
Java言語仕様において長らくの問題(課題)であった「データを表したいだけなのに、書く必要があるコード量が多すぎる」に対する解決策として、レコード型がサポートされました。基本的な使い方は型の名前とそこに含めるメンバを宣言するだけです。通常のクラスの宣言と異なるのは、`class`の代わりに`record`と宣言すること、型名のあとに引数を宣言する必要があることだけです。この引数が扱う「データ」となります。
具体的に言うと上のコードを記載すると下のようなコードに書かれているフィールドやメソッドが自動的に生成されるイメージです。書かれている通りに順番に言うと、
- 値は書き換えられない。つまりデータを表すフィールドは final になる。
- 値の取得はgetter経由で行う。このgetterは変数名と同じになる。getHogeは作成できない(されない)。
- 入力値に対する処理を行うことも可能です。
- インタフェースを実装できます、ただし継承(拡張)は不可能です。なぜならすでにjava.lang.Recordをextendsしているからです。
- 何度か触れてますが、新しいクラスじゃない「型」が導入されたように見えますが、バイトコードを覗くと実態は`java.lang.Record`を拡張したクラスであることが分かります。このクラスでtoStringなどのコメントアウトしている3つのメソッドが抽象メソッドとして宣言されているので、これらのメソッドがコンパイル時に自動的に生成されます。
Java 15ではこの基本的な使い方は変更されていませんが、一般的なクラスにおけるローカルクラスに対するローカルレコードという機能の追加などの変更が組み込まれています。
どういうことかというと、レコードを扱いたいアプリケーションとして考えられるパターンとして、あるクラスの中に単純な変数を複数持つ内部の値を扱うことが考えられます。現在は、こういった内部の値をヘルパークラスで扱っている実装が多いと考えられますが、これをレコードタイプとして扱えるようにする、というモチベーションです。
これ以外に後ほど説明するSealedクラスなどの対応も行われています。今後も変わる可能性があるので、実装について興味がある方は最新javacでコンパイルした結果をjavapでバイトコードを確認して確認することをお勧めします。
Java 13から導入されたテキストブロックがセカンドプレビューになりました。変更点は改行と空白を示す2つのエスケープ文字が導入されただけです。
具体的な使い方は表示されているとおりです。例えばやたら長い長文を記述したい時でもコード上ではみやすさのために改行を加えたいだとか、文末に空白を明確に記述したいときだとかに使うことができます。
この機能はJava 15で標準機能として昇格しました。
Javaアプリケーションで利用するメモリはGCによってJavaヒープ上で管理されます。しかしながら、アプリケーションによってはJavaヒープ外のメモリにアクセスしたいケースもあります。
これまではByteBufferの`allocateDirect`メソッドを利用する方法や、JNI(_Java Native Interface_)を利用する方法がありました。ほかに非公式ですが、`sun.misc.Unsafe.allocateMemory()`を利用する方法もあります。
しかし、これらの方法にはいくつか問題があります。
ByteBufferは1オブジェクトの上限がInteger.MAX_VALUE(2G)に限定され、全体で`-XX:MaxDirectMemorySize`で指定した値以下にする必要がありますが、メモリ割り当て解放のタイミングはGCに委ねられているため、意図せず超えてしまう問題がありました。
また、JNI(_Java Native Interface_)はC言語などでコードを書く必要があり、メモリ管理をすべて自分で行う必要があります。
そして、`sun.misc.Unsafe`クラスは非公式であるため将来的に無警告で削除される可能性があるうえ、名前のとおりに容易にJVMをクラッシュさせる安全でない操作を引き起こすことができるという問題を抱えています。管理してないメモリをいきなり触るとか。
このため、Java 14からはJavaヒープ外のメモリを扱うためのJava APIが新たに導入されました。JEPのページでは、メモリへの逆参照を行うサンプルとしてこのようなコードが示されています。
なお、このAPIはIncubatoorと書かれていますが、これは今後APIが削除されたり変更される可能性があるAPIを指し、標準モジュールとは異なる特別なモジュールで提供されています。本来は非互換性を極力廃するように変更が行われますが、これらのAPIはその対象外です。このAPIを利用する場合は`--add-modules jdk.incubator.foreign`を指定する必要があります。
また、このAPIはかなり広範囲がサポートされており、次のバージョンではAPIの利用方法が変わる可能性があります。Java 15でもmapped memory segmentのサポートが拡張されるなど、多数のAPIのリフレッシュが行われています。興味がある方はぜひAPIドキュメントを参照しながら使ってみてOpenJDKコミュニティにフィードバックしてください。あなたの貢献により良くなる可能性があります。Records以上に変わる可能性があるので常に最新APIをドキュメントから確認するようにしてください。
ここから Java 15 で追加された機能です。Java 15では新たに二種類のクラスが追加されました。この内の一つがシールドクラスです。
これは誰がサブタイプになれるかを完全に制限することが可能なクラスです。これによって今までのアクセス修飾子よりも、クラスやインターフェースの作者が、より明示的にどのコードが実装を担うかを宣言することができるようになりました。副次的な効果として、サブクラスを完全にコントロールすることができるので、パターンマッチングもより網羅的に行うこともできるようになります。
通常のクラス宣言と違うのはclassの前にsealedと宣言すること、そして継承や拡張を許可するサブタイプを`permits`宣言のあとに記載します。今回はパッケージ名も含めてFQDNで記載していますが、同一パッケージであればクラス名だけで指定することも可能です。
特徴としては、封印された型の匿名のサブクラス(およびラムダ)は禁止されています。また、特に指定がない限り、sealedのabstract、つまり抽象的なサブタイプはsealedとなり、通常のサブタイプはfinalとなります。各サブタイプの宣言時に`non-sealed`と明示的に指定することでこの制約は回避することができます。
もう一つはHidden Classesと呼ばれるクラスです。このクラスは限定された方法以外では他のクラスやインターフェースからはアクセスできない、他のクラスから完全に秘匿されることを目的としています。
完全に秘匿するということはどういうことでしょうか?実は今までの実装ではリフレクションを利用するなどで無理矢理読もうと思えば読むことができるのです。
現在の実装はあるクラスのバイトコードがコンパイル時に作成されたもの(静的クラス)か、ランタイム時に作成されたもの(動的クラス)かを区別しません。なお、コンパイル時に作成したものを静的クラス、ランタイム時に作成したものを動的クラスと言います。このため、ある動的クラスが同じクラスローダー階層にいる別のクラスから名前を元にリンクしようとする度に可視化されてしまうため、完全な秘匿を実現する方法がありませんでした。これによって、動的クラスのライフサイクルがリンクしている静的クラスが開放されるまで保持され続けるなど、想定以上に長くなってしまう問題がありました。
これを回避するために、フレームワークにより実行時に生成され、他のクラスから秘匿されつつリフレクションを介して間接的に使用でき、他のクラスから独立してアンロードできることを目的としたのがHidden Classesです。
通常のクラス、またはインターフェースは`ClassLoader::defineClass`を呼び出すことで作成されますが、隠しクラス、インターフェースはMethodHandles.Lookup#defineHiddenClassを呼び出すことで作成されます。このメソッドはbyte配列から隠されたクラスを生成し、reflective accessをもつlookupオブジェクトを返します。このlookupオブジェクトが隠しクラスのClassオブジェクトを取得する唯一の方法となり、他の方法からはアクセスできないようにすることで、完全な秘匿を達成しています。
このほか、細かい変更としては次のようなものがあります。
まず1つは、LegacyなSocket APIの再実装がJava 13で行われました。これに基づき、周辺APIの再実装を進めようという内容です。この実装はJava 1.0から導入されており、C言語とJava言語が共存している状態でメンテナンス性が損なわれていました。他、非同期クローズなどの並行処理で難があったのでそういった部分の改善が行われる予定です。
ByteBuffer APIが不揮発性メモリにも対応しました。
`java.rmi.activation`パッケージに属するクラスやインターフェース及び関連クラスが非推奨化され、`rmid`ツールが非推奨化に伴い警告が出るようになりました。
つづいてJVMの挙動に関する変更について紹介していきます。この変更は大きなものが2つあります
(きしださんが説明するので21までSkip。以下は元ある原稿)
本来はnullを想定していない処理中にJavaアプリケーションがnullを受け取ってしまった際に、`NullPointerException`が発生します。
Javaのコードを書いたことがある人にとっては、NPEは珍しくないと思いますが、念のために説明すると、NPEの基本的な対処方法は、スタックトレースから例外が発生したコードの行を確認し、どのオブジェクトがnullとなったかを推定することでコードの修正を行うことが挙げられます。
例えば次のようにSampleクラスを実行した結果、NPEが発生したスタックトレースを受け取った場合は、Sample.javaの4行目に`null`となったオブジェクトがあったと判断することができます。
もしこのSample.javaの4行目が次のようなコードだった場合、Nullとなっている可能性があるオブジェクトは`person`か`person`が持つ`name`の二箇所であり、比較的範囲が絞られているため対処も簡単です。
今回に関して言えば8行目でnameにnullを入れているので明らかにこれが原因です。
しかし次のコードのように、オブジェクトを多数利用している場合はどこでnullになったのか一見では解らないぐらいに被疑箇所が多く、かつそれぞれのオブジェクトがまったく別の処理で作成していた場合では、調査に時間を要することも珍しくありませんでした。
現実的には三次元配列はめったに使わないし、オブジェクトがNullableかそうでないかは考慮したうえで実装しますが、世の中思わぬところでnullになって調査が難航することは稀に良くあります。
このため、Java 14からはこのオプションを設定することで、具体的にどの処理を行った際にどのオブジェクトがnullだったかを表示するように変更が行われました。
このオプションを付けて先程のSampleクラスを改めて実行してみましょう。
ちょっと見にくいのでエラーメッセージを改行してみます。今後出るエラーメッセージも必要に応じて改行しています。
このように、どのような処理中にどのオブジェクトがnullであったかを完璧に表示しています。これによって先程のようなメソッドでもどこがnullであったかを知ることができます
nullを表示するエラーメッセージは処理やnullの箇所に応じて出力内容が変わります。特にローカル変数についてはひと手間必要なので追加で紹介します。
次のようなローカル変数`names`がnullになっていたケースを見てみましょう
実際に実行してみるとObject配列を読み込もうとした際に(When)ローカル変数(What)がnullであったため読み込めなかったことを示しています。実際のローカル変数名はここに書かれている内容(`local1`を指す)ではありませんが、通常のコンパイル方法ではローカル変数情報が含まれていないためこのような表示のされ方をします。
ローカル変数の名前を明確に表示したい場合はローカル変数を含むデバッグ情報が必要なため、次のようにクラスファイルをコンパイルする際に`-g`オプションを指定する必要があります。
`local1`ではなくローカル変数の名前が`names`と明確に出力されるようになりました。
この出力は非常に便利ですが、ローカル変数のデバッグ情報が増えるため、クラスファイルのサイズが増大するため配布時に影響が出る、クラスロードを行う時間が多少延びる、そしてリバースエンジニアリングのヒントが増えて行いやすくなるという問題もあります。このため、このオプションは基本的には開発環境で利用することをお勧めします。
この機能全体の懸念点としてパフォーマンスへの影響が挙げられますが、NPE発生時、正確にはスタックトレースの生成時にメッセージを取得するようにしているため、特筆すべきレベルの大きな影響はありません。頻繁にNPEを発生させているアプリケーションの場合は性能に影響がある可能性もありますが、そのようなアプリケーションはそもそも処理の見直しを行ってからパフォーマンスを確認してください。
Biased Lockingがデフォルトで無効化されました。
このBiased lockingはuncontented lockingのオーバヘッドを下げるためにHotSpot VMにかなり早い時期に導入されました(当時はOSSじゃないので伝聞です)。
これは、あるthreadがmonitorを取得しようとするまでモニタは特定のスレッドに所有されたままであると仮定することでatomic操作回数を減らし、多くのスレッドがシングルスレッド方式で使用しているオブジェクトに対する同期操作(を多く行っているケースで)の性能改善を図っていました。
初期のAPI(java.util.Vectorなど)はアクセスの度に同期をとる実装になっており、非同期コレクションはJava 1.2から、マルチスレッドを考慮したAPIはJava 5からと導入が遅めだったため、初期は実際に目覚ましい効果がありましたが、並列処理用のAPIが充実してきた昨今では逆に性能が悪化している(ベンチマークツール、SPECjbbより判明)状況でした。
また、Biased lockingによってJVMのコードもメンテナンスしづらくなっているので非推奨化して最終的には削除する方針となり、Java 15からはデフォルトで無効になりました。
- XX:-UseBiasedLockingで以前のJavaでも無効化することは可能です。逆に有効にしたい場合は-を+に変更することで可能ですが、将来的には削除されるので無効化するのが望ましいでしょう。
(練習通りいくと時間が足りないので、GCについてはまとめてこのスライドで説明する。27までskip、以下は元ある原稿)
続いてGC関係について説明していきます。Java 14では細々とした変更が入り、Java 15では試験的なGCが標準機能となりました。
Java 15で導入された2つのGCを軽く説明すると、ZGCはテラバイト級までの巨大なヒープを扱いながら、アプリケーション停止時間を10ミリ秒以下にすることを目的としたGCで、Shenandoah GCはG1 GCのようにリージョン単位でヒープを管理しつつ並列コンパクションを採用したGCです。
NUMAとは複数のプロセッサが共有しているメモリへのアクセスコストを、プロセッサとメモリ領域ごとに偏りを持たせたアーキテクチャです。
しかし、JavaはGCによってメモリ管理が行われているため、未対応であったG1 GCを利用している場合は、この偏りを無視してメモリを利用する可能性がありました。
現在のデフォルトであるG1 GCは、NUMAノードを意識してヒープリージョンの配置を行うように改善が行われました。
これにより、NUMAアーキテクチャを採用しているサーバ上でG1 GCを利用してJavaアプリケーションを運用している場合、パフォーマンスの改善が見込まれます。
非推奨であったCMS GCが完全に削除されました。
ただし、オプションを指定して実行すると、このような警告が出てデフォルトのGC、今だとG1 GCが選択されて実行されます。poorな環境だとSerial GCが選択されます。
起動失敗しないのでCMSのつもりでG1で動いてて「アプリケーションの動作がおかしい!」とか「ログ内容がおかしい!」とならないように注意しましょう。
いずれにしてもGCアルゴリズムはちゃんと明確に指定しましょう。
Java 11から試験機能として導入された、テラバイト級までの巨大なヒープを扱いながら、アプリケーション停止時間を10ミリ秒以下にすることを目的としたZGCはLinuxのみだったが、macOSおよびWindowsでも利用できるようなりました。
ZGCは弊社のHBaseチームが検証して記事を出してますので興味ある方はそちらを確認してみてください。
次のようなオプションでYoung GCをパラレルで、Old GCをシリアルでGCを実行する組み合わせが非推奨になった
(補足)
一般的に、システムリソースを気にするならYoung GCのほうが実行回数が多いので、こちらをシリアルにしてOld GCも合わせてシリアル、または回数が少ないのでパラレルにするのは合理的だが、逆にするシチュエーションはあまりないのでメンテナンス性を考慮して将来的に削除される予定となった。
最後にツールの変更です。これはJava 14の変更のみです。
(補足)
ただし、JEPにはなっていませんがJava 15でも`rmic`が削除されたりはされています
パッケージングツールです、平たく言うと各OSに合わせたインストーラーを作成するためのツールです。
Windowsだけは外部のWiXツールを追加でインストールする必要があります。
このツールはincubatorなAPIに依存しているため、incubatorと記載されています。
今後のJavaアプリケーションを提供する流れとしては、カスタムランタイムイメージをjlinkで作成し、その後インストーラをこのツールで作ってユーザに提供する、と想定されています。
`--input`でjarファイルが置かれているディレクトリを指定し、メインJARファイル、メインクラスをそれぞれ指定して実行します。すると、macOSであればsample-1.0.dmgなど、OSに合わせたインストーラが作成されます。
カスタムイメージでの作り方は依存しているモジュールを表示する。モジュールを指定してjlinkでカスタムイメージを作成する。
そしてこのツールで`jlink`で作ったカスタムイメージを`--runtime-image`で指定しているだけです。この方法を利用するメリットはインストールされるサイズが抑えられることと、インストーラそのもののファイルサイズも抑えられるところです。
JavaはRun anywhereを掲げておりJARファイルの提供だけで済むのが言語のメリットの一つではありますが、Javaの実行バイナリがより多くのベンダや団体から提供されるようになったので、このようなインストーラでバイナリごとインストールさせるメリットが以前より大きくなったと捉えることができます。
(いとうさんが説明するので37までskip、以下は元ある原稿)
HeapStatsの商売敵というか元々プロプライエタリであったOracle社製トラブルシューティングツールであるJava Flight RecordがJava 11からOSS化され、つい最近例外中の例外的にJava 8にもバックポートが行われました。
Javaは商標なのでJDK Flight Recorderという名前になりました。
このJDK Flight Recorderにストリーミング機能が新しく追加されました。これまではJFRで取得した情報はダンプしたファイル経由で読み取る必要があり、リアルタイムでのモニタリングが行いにくいという問題がありました。
この新機能により`RecordingStream`クラスを通じて、リポジトリを経由して別のJavaプロセスから継続的に取得したり、もちろん同じJavaプロセス内でも取得したりすることが可能になりました。
まずは次のJFRSampleクラスのように、JFRをローカルで開始して記録を行い、ストリームを作成して継続的に標準出力してみましょう。このクラスを実行すると、CPU負荷イベントを10秒ごとに出力します。
CPU負荷イベントの情報はこんな感じで出力されます。
単純に定期的に出力するには分かりやすい値だったためCPU情報を収集していますが、他にデフォルトで用意されているイベントを収集することができます。用意されているイベントはJDK内のhttps://hg.openjdk.java.net/jdk/jdk14/file/e568ce785bdf/src/hotspot/share/jfr/metadata/metadata.xmlに定義されています。
ThreadStartやThreadPark、JavaMonitorなどのスレッド情報から、ClassLoadなどのクラスローディング情報、ヒープ使用量や各GCアルゴリズムごとの統計情報など多種多様なイベントを出力できます。
これ以外にもJFR APIを利用して、具体的にはjdk.jfr.Event(https://docs.oracle.com/en/java/javase/14/docs/api/jdk.jfr/jdk/jfr/Event.html)クラスを拡張することで、自分で独自にイベントを作ることも可能です。この機能は今回導入された機能ではなく、Java 9から提供されています。
また、JFRはどういったイベントを有効にするかの情報が設定されている基本構成としてdefaultとprofileの設定が用意されており、この構成を利用してストリームを作成することも可能です。記録するイベントの設定漏れを防げるなどの理由から、基本はこちらのほうがお勧めです。
なお、profile構成を利用した場合は出力される情報量が多いため、それなりにJavaアプリケーションにオーバーヘッドが掛かるので注意してください。いきなりプロダクションで有効にするのではなく、性能がどれだけ落ちるか確認したほうが良いでしょう。
ローカルJavaプロセスの情報であればなにもJFRを利用する必要はありません。あるJavaプロセスで収集しているCPU負荷イベント情報を、別のJavaプロセスから取得してみましょう。そのためにはまずは、対象JavaプロセスのJFRリポジトリパスを`jcmd`から確認します。
このリポジトリパスはデフォルトではOSのテンポラリディレクトリですが、Javaの起動時にこのオプションを使って指定することもできます。
このリポジトリパスへのストリームをJFRRemoteSampleのように開くことで、別のJavaプロセスから監視を行うことができます。せっかくなのでメソッドプロファイリングを行うイベントを標準出力しました。
このように別のJavaプロセスからもリポジトリを参照することで、リアルタイムに情報の収集が行えます。
なお対象のJavaプロセスを終了するとストリームが終了するため、自動的に収集も終了します。また、対象Javaプロセスで記録していない情報以外は当然ながら収集することはできません。
これまではファイルをダンプして事後解析が必要でしたがこれによりだいぶ楽になりました。リポジトリを見れば最大でも1秒以内というほぼリアルタイムで時系列データを得ることができ、事後解析も楽にすばやく取りかかることができると期待できます。
注意事項として、JFRは様々な情報が収集できるため多角的な解析手段としては最高峰ですが、OOMEやクラッシュ時のメモリ情報収集は苦手であるということに注意してください。
Leak Profilerの実装的な問題により、長期的なメモリリークであれば収集できる可能性は十二分にあるが、超短期間のメモリ使用量上昇、ようは瞬間的なスパイクによるOOMEであればオブジェクトサンプリングが取得できない可能性があります。
このため、JFRとは別に`HeapDumpOnOutOfMemoryError`オプションでプロセスが死亡する際にヒープダンプを取得する必要があります。
この他、細々とした変更点として、新しい暗号署名が追加されました。
Java 8で導入され、Java 11で非推奨化されたJavaScriptエンジンであるNashornとjjsツールが削除されました。
そしてSplarisとSPARCポートが削除されました。
以上です、ご清聴ありがとうございました
ボードゲームを普段遊ばない人と楽しみたい
ボドゲはいいぞ。この記事はpyspa Advent Calendar 2019の18日目です。
ボードゲームを普段遊ばない人をすっと沼に沈めてボードゲームで遊べる友人を増やしていきたい。
ボードゲームのとっつきやすさを決める要素は、個人的にはおおざっぱに次のようになると考えている。
- 複雑さ
- ルールの複雑さ。あるいは最初のルール説明(「インスト」とよく呼ばれる)の長さ。ルールを説明されてすぐ何をすべきか分かるかどうか。
- 難しさ
- 勝利するために必要な手を考えるむずかしさ。複雑さが原因になりやすいが、それ以外にも選択肢の多さや操作すべき要素の量が難しさにつながる。
- 時間
- プレイ時間。「軽量」ゲームと呼ばれるものはプレイ時間が短い。逆に複雑さ・難しさが高いと一人あたりの時間が伸び、結果としてプレイ時間も伸び、「重量」ゲームと呼ばれる。
- 人数
- 重量系は4人用が比較的多い。
これを踏まえて、4-6人用を目途に普段遊ばない人を誘いやすい「とっつきやすさ」に振り切ったボードゲームをリストアップしてみた。
反射神経系ゲーム
目の前にある情報を元に素早く対応した人が勝ちなゲーム。いわゆる早押し。
1-2回試しにやってみれば即ルールが分かるのでとてもとっつきやすい。子供の方が強いケースもある。
ただし、反射神経が物を言うゲームなので強い人がめっぽう強い。そういった場合は酔いを入れてカオスを持ち込みましょう。
お化けキャッチ
5種類のコマを中央に置き、カードをめくってそこに書かれていない「色」と「形」のコマ、あるいは「色」と「形」が完全に一致しているコマを一番早く取った人が勝ち。
ルールが二種類あるので分かったつもりでも間違えることがあり、飽きにくく面白い。勢いよくコマを取っても多少の事では壊れないので子供にもおすすめ。
Dobble
それぞれのカードに8種類の絵が描かれている。中央に置かれたカードと自分のカードに共通している絵が必ず一つだけあるので、それをコールして早く取るゲーム。
強い人が割と本当に強いゲームなので一方的になりやすいことがままある。
積み木系ゲーム
ジェンガのようにモノを手に取って操作することで決着をつけるゲーム。モノの制約上、ルールがシンプルなのでとっつきやすい。問題は「ボドゲか?」という点と持ち運びが不便な点。あまり気にしないで進める。
スピードカップス
カードに書かれている通りに、手元にあるコップの色と並べ方を揃えてベルを鳴らせば勝ち。
反射神経系でもあるが、モノが絡むと意外に時間が懸かったりする。
バンボレオ
不安定な台の上に様々なブロックが置かれており、崩さずにとっていき最後に崩した人が負け。シンプルかつ強い人は定まりにくいので盛り上がりやすい。
ただし高い。
連想ゲーム
コトバーテル
五文字の言葉を敵チームと交換し、カタカナ一文字を表すカードを山札から引いて味方に伝えるゲーム。
ルールはシンプルだが人によって伝え方が意外に癖があるので、少しずつ伝えようとしている言葉が分かるにつれ盛り上がりやすい。
最近のProject Jigsaw の流れ:コミュニティ投票でNo (Public Review Ballot)
Java の新たなバージョンである JDK 9 のリリースが約 2 ヶ月後に控えているが、最大の目玉と言っても過言はない Project Jigsaw がコミュニティから No を突きつけられた。この最近の流れを、極力意見を混ぜずに事実を淡々と紹介する。
Project Jigsaw とは
前提
- Java の機能は JSR (Java Specification Request) が JCP (Java Community Process) で承認されて初めて導入される
- Project Jigsaw も例外ではなく JSR 376: Java Platform Module System により JCP の承認プロセスを進めている
- JSR や JCP についての日本語解説は @yy_yank 氏の記事や @miyakawa_taku 氏の資料、浜松氏の資料 が参考になる。
最近の流れ
Project Jigsaw は Draft Releases の期間でした。なお、私は OpenJDK 実装をそれなりに読んでおり、各自の立場から反対意見の要約を示すことができないと思いますので、詳細な内容は紹介しません。詳しくはリンク先を確認してみて下さい。
2017/1/17 - 2/16 Early Draft Review
3/21 - 4/20 Public Review
- 公開審査(Public Rewiew)の名の通り、一般も含めてレビューやコメントを受け付け、 Spec Leadは全てのコメントを受けて検討を行う
- 4/14: Red Hat が反対意見を記事で公開
4/25 - 5/8 Public Review Ballot
- Executive Committee (執行委員会、以下EC) による投票が行われ、Public Review の承認可否判定が行われる
- ちなみにこれが通っても次は Final Release というフェーズに移り最後の投票が残されてる
- 4/28: IBM が JSR 用のメーリングリストで懸念と反対票に投じることを表明
- Concerns with JPMS spec and Jigsaw implementation
- 5/1 に InfoQ にもこの動向が掲載される:IBM and Red Hat to Vote "No" on Java Modules (Jigsaw)
- 5/5: Spec Lead (Oracle, Mark) が記事で反論を掲載
- An Open Letter to the JCP Executive Committee | Mark Reinhold
- 他の EC member に特定企業の利益のために否決されないように冷静な判断を望むという所見を示した
- 5/5: Red Hat がメーリングリストに反対理由について説明を投稿
- 5/8: Mark が上記反対理由について反論
- 5/8: 賛成 10, 反対 13 で否決。賛成票もコメント付きで次回までに改善を望んでいる物が多数でした。
これからどうなるか
JCP で定められている通り、否決された場合は Spec Lead と Expert Group は 30 日以内に EC から提起された懸念に対応するための仕様草案の更新・修正を行い、再び審査投票を実施します。この審査投票でも否決された場合は JSR は終了し、Expert Group は解散されます。
ただ、JDK 9 のリリース予定日が 7/27 と差し迫っている中、懸念に対する仕様変更はまだしも、その実装は更に時間がかかる可能性が高く、リリースにも影響が及ぶことは十分に考えられる状況です。現在はまだ投票結果が出たばかりなので、今後の動向に注目していく必要があります。
追記
追記1:Jigsaw 否決の内情について
EC member は全団体が頭ごなしに No と表明しているわけではありません。その一例として Tomitribe のコメントを紹介します。
Though a No vote feels like rejection we ultimately believe it is the most supportive vote for gaining a greater level of consensus we believe is necessary from a JSR, while still keeping time pressure.
Jigsaw における技術的な課題について指摘している団体もおりますが、懸念について駆け込み的に対応しようとした Expert Group とのコンセンサスの取り方について疑問を持ち、最初の投票で Yes と投じにくいと判断した団体も多くいるようです。各団体のコメントは投票結果のページから確認ができます。
追記2: JDK 9 の JSR
JDK 9 も同じタイミングで JSR 379 Java SE 9 Release Contents にて JCP の承認プロセスを実施していますが、こっちは賛成多数で可決しました。
jcmd と既存ツールの対応
はじめに
この記事はJava Advent Calendar 2016の 1 日目の記事です
先日の Java Casual #2) で jcmd について話してきました。
jcmd は Oracle 社のドキュメントでは推奨ツールとして扱われており、jps や jmap, jstat のような既存ツールは "Experimental" とされています。このため、既存ツールから jcmd への移行が進められる可能性があります。例えば Experimental であった jhat は Java 9 から削除されます。
Java 9 からの新機能を含めた jcmd の各種機能は上記スライドを見ていただくとして、ここでは jcmd でどのように既存ツール相当の機能が使えるかを紹介したいと思います
OpenJDK のリポジトリから特定バージョンの Java のソースコードを落とす方法
例:JDK8u77 のソースコードを落としたい
解説
- OpenJDK のソースはタグ管理されているので、JDK8 Updates Master のタグ一覧を確認する
- u77 の最新の b 番号は b03 なので jdk8u77-b03 が取得したいソースコード
- これを mercurial コマンドと OpenJDK のツールから持ってくる
- jdk8 以外は jdk8u の部分を適当に入れ替える。(※ただし動作確認してません)