2019年7月21日日曜日

Ryzen 5 2600XでAndroid Studio のx86エミュレータを使えないWindows May 2019 Update

WindowsのAndroid StudioではAndroidのエミュレータが使えるのですが、x86版のエミュレータにはIntelのVT-xかAMDのSVMをUEFI(BIOS)上で有効にする必要があります。
今回はAMD Ryzen 5 2600xなので初回セットアップでVT-xつかえないよといわれ、UEFI上でSVMを有効にしてみました。OSのバグかなにかで失敗したのですが、いろいろ調べた挙げ句のメモです。
AndroidエミュレータがAMD CPUとHyper-V に対応した、というニュースのAMD CPUとHyper-Vは別々の話なので混ぜるな注意です。Hyper-VはAMD CPUにたいおうしていないっぽいたぶん。

Android Studioでエミュレータを動かす条件 3種類
  • Intel VT-x
  • AMD SVM
  • Microsoft Hyper-V
どれかが必要、ということらしいので今回はAMD SVMを有効にする方法

今回の前提

AMD Ryzen CPU
Windows 10 Pro April 2018 Update 以降 (Homeでも可?)
Windows 10 バージョン 1903 (OS ビルド 18362.239) (失敗するバージョン)
Android Studio 3.4.2 (3.2 Beta以降)
Avastかなにかのソフト使ってないこと

状態の確認

Windowsのバージョンを確認します。
スタートメニューを右クリックで「システム(Y)」を開き、Windowsの仕様というところにバージョンとOSビルドがあります。
コマンドプロンプトでwinver と入力してもバージョンが確認できます。
バージョン1903 (OS ビルド 18362.239) と出てくればバグ持ちなのでエミュレータは動きません。(注 : 7月末のKB4505903のアップデートでOS ビルド 18362.267になり修正されました)
エミュレータが実行可能なのは現状では1803と1809です。
Windows Insider Programで18932を使用するとエミュレータが利用可能という情報もありますが、元には戻せません。

AMD RyzenでAndroid x86エミュレータの利用可能状況(1803以降対応)
○ バージョン 1803 April 2018 Update
○ バージョン 1809 October 2018 Update
× バージョン 1903 May 2019 Update (OSビルド 18362.239)
○ バージョン 1903 May 2019 Update + KB4505903 (OSビルド 18362.267)
○ ビルド 18932

コマンドプロンプトで systeminfo
最初にOSのバージョンなど、最後にHyper-Vの要件が4つ出てきます。

systeminfoのHyper-Vの項目で、ファームウェアで仮想化が有効になっています : いいえ
となっていれば、UEFIの設定を変更します。
4つとも有効になっていればWindowsでハイパーバイザーを有効にします。
ハイパーバイザーが検出されました。と出てくればWindowsの設定も済んでいるのでAndroid Studioの方へ

UEFIの設定

仮想化技術はふつう使わないのでUEFIの初期設定でも無効化されていることが多いようです。
今回はASUSのTUF X470-PLUS GAMINGというマザーボードです。
Windowsを再起動させ、起動する前にdelete(DEL)キーでUEFIに入ります。キーボードもマウスも使えます。メニューを日本語にすることもできます。
UEFIの詳細設定の方を開き、CPUのSVMという項目をなんとなく見つけてEnabled にします。他の項目は触らなくてもいいですがてきとーに設定して保存して再起動します。

Windowsの設定

Windows 10では設定のメニューがコンパクトになってしまったのですたーとメニューから[Windows システムツール]→ [コントロールパネル]と開きます。[コントロールパネル > すべてのコントロールパネル項目] と開いていればOK。
[プログラムと機能]を開き、左の[Windowsの機能の有効化と無効化]までたどりつきます。
関連する項目は2つ
 [Hyper-V]のチェックをはずします。もともとはずれているはずです。
 [Windows ハイパーバイザー プラットフォーム]をチェックします。
Windowsの再起動をします。
systeminfo でHyper-Vの要件にハイパーバイザーが検出されました。と表示されていればWindowsまでの準備は終了のはずです。

Android Studo

ToolsからSDK ManagerとAVD Manager を開き、環境を整えます。

SDK Manager


[SDK Tools]の Intel x86 Emulator Accelerator (HAXM installer) はAMD Ryzenには不要なので入れてしまったら削除します。
Android Emulator、Android SDK Platform-Tools、Android SDK Toolsなどが入っていれば大丈夫なのかもしれません。

AVD Manager

VT-xが有効ではありません、などのエラーメッセージがでたら、Windowsハイパーバイザーの設定までがうまくいっていないので、もう一度UEFI、Windowsの設定を見直してください。
ここまでで起動しない…。
Windows バージョン1903 (May 2019 Update)はバグ持ちのようなので、次のアップデートまで待つしかないようです。(7月末 Updateで修正済み)

Hyper-Vだとどうなる 

Android エミュレータはHyper-Vにも対応しています。試してみましょうか。Hyper-V側をチェックし、ハイパーバイザーをはずして再起動します。Android StuidoではVT-xか何かがないよというメッセージが表示されるだけで使えませんでした。

参考
 窓の杜 https://forest.watch.impress.co.jp/docs/news/1132197.html
 Android StudioとAMD製CPU https://blog.misatowater.com/entry/tech/amd-androidstudio

2019年7月15日月曜日

MavenでTomcatにJAX-RSのせるだけ

TomcatにはJava EE 改め Jakarta EEのWeb系の機能しか載っていないので、その他のサービスを利用するにはwarの中に封じ込めてあげるのが楽です。
とりあえずJDK 12 + Apache NetBeans IDE 11.0の場合
Mavenで構築、Tomcatに公開する場合です。
GlassFishのJAX-RSライブラリを使います。

MavenでWebつくる
JAX-RS の機能でRESTfulなものを作る

Servlet相当のクラスをひとつ作り、タグだけつけます。Applicationというクラスを継承するようです。@ApplicationPath で公開パスを決めます。

package net.siisise.example.rest;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/api")
public class RestSetup extends Application {
}

次に機能のclassを作ります。
@の機能は推測どおりかと思うので GET /api/menu/hello に公開されます。

package net.siisise.example.rest;

@Path("/menu")
public class Mmmmm {
    @Path("/hello")
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String exHelloName() {
        return "おはよう";
    }
}

そのまま公開してもTomcatではライブラリ等不足しています。

web.xml の編集。GlassFishサーバの設定をしていると、<dependencies> にjavaee-web-api があるかもしれません。
(Bloggerの都合上XMLタグは全角で囲んでいます。)

<dependencies>
   <dependency>
       <groupid>javax</groupid>
       <artifactid>javaee-web-api</artifactid>
       <version>7.0</version>
       <scope>provided</scope>
   </dependency>
</dependencies>
これはコメントアウトします。

<dependencies>

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>2.29</version>
    </dependency>
    <dependency>
       <groupId>org.glassfish.jersey.inject</groupId>
       <artifactId>jersey-hk2</artifactId>
       <version>2.29</version>
    </dependency>
</dependencies>
とりあえずこのふたつがあれば動くようです。Servletを手動で設定する必要はありませんでした。
ビルドしてデプロイすれば /api/menu/hello で動いてくれます。
JAX-RS のMavenパッケージは jakarta.ws.rs-api というのに変わっていくっぽいです。

Web Application Description Language (WADL)

それから JAX-WS の SOAPにWSDL があるように、JAX-RSなRESTにはWADL というのがあるようで、これにはJAXBのライブラリも必要らしい。
仕様 https://www.w3.org/Submission/wadl/
<dependency>
  <groupId>javax.xml.bind</groupId>
  <artifactId>jaxb-api</artifactId>
  <version>2.4.0-b180830.0359</version>
</dependency>
<dependency>
  <groupId>org.glassfish.jaxb</groupId>
  <artifactId>jaxb-runtime</artifactId>
  <version>2.4.0-b180830.0438</version>
</dependency>
少し省略して書く。
 /api/application.wadl が表示されればOK、エラーなら何か見直し。

JSONとかいうもの

しばらく前からJSONとかRESTとかいうものがプログラムとか通信とかの間で使われるようになってきていたけど、全然追ってなかったのでいまさら追いかけた。 追いかけた足跡だけで細かいことは省略。
OpenIDを開いてみた気がする…。

JSONを広げる

 避けていたのは認証とかそういうところにたどり着かなかったから。今なら簡単に見つかりそうな気もする。 とりあえず仕様を探せ。JSONはRFC 8259が最新で最終版ともいわれている。ECMAの方にもECMA-404 2nd Edition というのがあるのでそれまでにあった差異などが解消されているとか。 名と値を文字列で書いたオブジェクトっぽいのがJSONの書式で、配列のもある。それだけ。JavaScriptとの受け渡しで相性がいいらしい。

RESTから関連機能を探す


 RESTは何だろうというと、HTTPやら何やらでJSONを通信する方法とでもいうか、HTMLの代わりにJSONが飛び交う。 どこで使われているのかというと、いろんなところで。XMLが流行ってたのは今は昔とでもいう勢いで。 各種サービス提供に使われているのはREST APIがほとんどらしいよ。と噂に聞いている。IoTの分野でも手軽にRESTで通信できるようになってる。人が間に入らないサービスはこういう方向でどんどん増えてもらいたい。
 RESTを使うのをRESTfulとかいうらしいよ。 ここまでは知ってた範囲。それで認証とかどうなのよというところで思考が停止。PKI使うのかBASIC認証使うのか、いろいろもやもやしてた数年前かな。
認証に使うのはRFC 2617 BASIC認証? とかCookieとかいろいろあった時代もあるようで。 RFC 7515-7519 というのがようやく安定してきた認証方法なのかな。この中からまずは JSON Web Token (JWT)を知ってみよう。PKIの基礎知識が必要。OAuth やOpenID Connect とやらもあるのであわせて後で調べる。

ABNFとJSON作ってみた

Javaで使うにはライブラリもあるのだろうけど、たまたま作りかけていたABNF(RFC 5234)で作ってみようと思ったらJSONの読み書きは簡単にできてしまったのでそういうことにしておく。
ABNFが何かというと、RFCで定義されているデータや何かの書式を書くための仕様で、プログラムで使うことはあんまり想定されていないけど作ってみたら案外使えなくもないしろもの。元はBNFという使いにくいものなんだけどRFC版のABNFは案外いろいろ書けるのでお得。曖昧な解釈とかも若干あるけども。EBNFとかBNFの派生にもいろいろあるけどまとめて実装しておいても使えないくらい他のは何もできないのでABNFは優秀。
ABNF自体もABNFで定義されているのでおもしろい。 プログラム上でもABNFを簡単にJavaにした形かABNFそのものですべての定義を書いている。

rulelist       =  1*( rule / (*c-wsp c-nl) )

というABNFの定義の一部を抜き出したサンプルと自作ライブラリの機能の紹介。
Javaでも次のように書けるので一部制限はあるものの、何も迷わない。

static ABNF rulelist = REG.rule("rulelist = 1*( rule / (*c-wsp c-nl) )";

事前の定義など省略するが、次のような書き方もできるようにした。パースする手間がない分起動が速い。

static ABNF rulelist = REG.rule("rulelist", rule.or(cWsp.x().pl(cNl)).ix());

文字列(ABNFtext)
static ABNF CRLF = ABNF.text("\r\n");
または ABNF CRLF = new ABNFtext("\r\n");

a / b / c は a.or(b,c)
a b c は a.pl(b,c) a.plus(b,c)はちょっと長いので縮めた
*element は element.x(0,-1) 略 element.x()
1*element は element.x(1,-1) 略 element.ix()
[element] は element.x(0,1) 略 element.c()
とJava中に手軽に書ける構造にしてみた。組み合わせも自由にできる。
a b c の構造は解析順序でどこまでをbに振ってどこからをcに振るのかなど複雑になることもあったので厳密版も作ってみたりしているが、改良版では厳密版の出番はまだない。

a*b element は element.x(a,b) と書く。
() はJavaの処理順で。
比較 Packetというデータの入れ物を昔から使っているのでそれの例

Packet pac = new Packet(data);
String str = "abc";
CRLF.is(pac) 判定(前方一致)
CRLF.is(str) 判定(前方一致)
CRLF.eq(pac) 判定(完全一致)
CRLF.eq(str) 判定(完全一致)
文字列でもどちらでも好きな方でデータの連結を考えて前方一致が使いやすそうなのでそれを基本に組み立てる。
テストで作ってみたのはRFC 3986 URIかな。 Parserまではまだ書いてない。

次のような注意点もあるのでABNFそのまま使えるわけではない点に注意。

RFC 2396 3.2.2. にある toplabel は原文では繰り返しとその後ろに alphanum が出てきてどちらなのかURIのパースで判定に困ることがあるので次のように修正してみたり。力業で読むこともできるのだけど。

 
原文 toplabel      = alpha | alpha *( alphanum | "-" ) alphanum ; BNF?

修正 toplabel      = alpha *( alphanum / ( "-" alphanum ) )     ; ABNF
 
ABNFは一旦略。
次はJSONのライブラリか。

JSONなどもABNFで定義されているのでちょちょっと追加するだけでABNFに加えBNF,EBNF,JSON,URL,URI,IMFなども使えるようになるのでRFCを収集しているところ。
JSONも基本はJSON構造を読んでJavaなら最終的にMapやListの階層構造と相互に変換できればいい。そういう作り方でいいんだろうか。ついでにBeanっぽいけどFieldを直接変換する作りも加えておいた。RESTの準備も進む。

各構文組み立てのためのParserはJavaで若干書くのだけど。構文解析の方はABNFのライブラリだけで可能。9割ぐらいABNF文に戻すこともでき処理順も目にやさしくなる。
ABNFを作ってからBNFとEBNFをさくっと作れたので、これくらいにしてJSONへ。

JSONはJavaScript Object なんとか RFC 8259 が最終形態らしい
オブジェクト、配列、Booleanや数値、文字、これくらいをシンプルに扱える。JavaScriptの内部表現的なものを誰かが発見して広まった、という解釈。
RFC 8259の式をそのままJavaに起こすだけで半分完成。ABNFのrulelistに流し込むだけでも同じ。JSONObjectとJSONArray、JSONValueなんていうクラスを作ってしまうとだいたい使える。Parserもさくっと中身の取り出し方に迷うくらいかな。
JSON→JSONObject→JavaのMap/List/配列→Object の相互変換が可能なくらいに仕上げてみた。
RFC 6901 JSON Pointer、RFC 6902 JSON Patch も動いた。
XMLよりJSONなのがよくわかる。

難しいのは文字コードの処理などかもしれない。JavaはUTF-8かUTF-16くらいで、UCSに変換とかサロゲートペアとか畳みかけてくるといろいろ面倒くさいが文字として扱えるよう注意してみた。
最初コンパイラでいうところの2PASSで実装したらしいABNFを1.5PASSくらいで書き直してみたりはした。 その他もろもろで初期から比べるとかなり速いがどっちが高速なのかは謎。
ABNFの拡張もいくつかあり、Parser書けばどこまででも対応はできるが、差分くらいで書けるようにしようとしてみるとどこまで対応していけるのか謎。
いろいろ言語的なものがさくっと作れるようになる、と期待。


https://github.com/okomeki にて公開中
RFC 7515から7519も作ってみないと次に進まない

 RFC 5234 Augmented BNF for Syntax Specifications: ABNF
  4. ABNFによるABNFの定義
  B.2.  Core Rules
 RFC 6901 JSON Pointer
 RFC 6902 JSON Patch
 RFC 7515 JSON Web Signature (JWS)
 RFC 7516 JSON Web Encryption (JWE)
 RFC 7517 JSON Web Key (JWK)
 RFC 7518 JSON Web Algorithms (JWA)
 RFC 7519 JSON Web Token (JWT)
 RFC 8259 JSON (本体)

NetBeansからGitHubへ

GitやGitHubがよくわかっていないのでNetBeans IDEから公開してみるテスト
説明は日本語サイトもあるけどあまり読んでいない。
  1. GitHubのアカウントを作る http://github.com/okomeki
  2. PuTTYgenで公開鍵を作る
    1. 画面上のPublic key をGitHubに登録する
    2. 秘密鍵をOpenSSH key形式で保存する
  3. リポジトリを作る https://github.com/okomeki/SoftLib
  4. SSHのURLを確認 git@github.com:okomeki/SoftLib.git (鍵を登録するとHTTPは不可?)
  5. NetBeansでプロジェクトをgitに入れる
    1. ローカルで作る
    2. Git → Commit
  6. Pushする
    1. Git → Remote → Push
    2. URLと秘密鍵、パスフェーズを指定
CVS/Subversionとの違い、疑問点のまとめ
  1. Gitはどこに溜まるのか
    最小単位はソースディレクトリの.git フォルダ内だけ
    管理専用の場所は不要
    Commitもこの中で完結、ひとりで管理可能
    CVSのブランチのようなものを保存場所で持つ
  2. GitHubにHTTPSで繋がらない
    鍵を登録していると無理なのか?
    ライブラリが古いとHTTPSは無理らしい、どちらか謎。
  3. アカウント/パスワードで繋がらない
    同上
というわけで
https://github.com/okomeki にいろいろと公開してみるかもしれません。