java.util.loggingを使用しないのはなぜですか?


351

私は人生で初めて、オープンソースになるJava APIを書いている立場にいます。うまくいけば、他の多くのプロジェクトに含まれることになります。

ロギングのために、私(そして実際に私が作業している人々)は常にJUL(java.util.logging)を使用しており、JULで問題が発生することはありません。しかし今、私は自分のAPI開発のために何をすべきかをより詳細に理解する必要があります。私はこれについていくつかの調査を行いましたが、得た情報を使用して、さらに混乱します。したがって、この投稿。

私はJUL出身なので、それに偏っています。残りについての私の知識はそれほど大きくありません。

私が行った調査から、人々がJULを嫌うこれらの理由を思いつきました。

  1. 「私は日が7月にリリースし、長い前に、Javaで開発を開始し、私がロギングフレームワーク-Xを続けることではなく、何か新しいことを学ぶことのためだけに簡単でした」。うーん。私は冗談ではありません、これは実際に人々が言うことです。この議論があれば、全員がCOBOLを実行できます。(私は確かにこれが怠惰な男であることと自分自身を関連付けることができます)

  2. 「JULのログレベルの名前は好きではありません真剣に、これは新しい依存関係を導入する理由には不十分です。

  3. 「JULからの出力の標準形式が気に入らない」。うーん。これは単なる設定です。コード的に何もする必要はありません。(確かに、昔は、正しいものにするために独自のFormatterクラスを作成する必要があったかもしれません)。

  4. 「logging-framework-Xも使用する他のライブラリを使用しているので、それを使用する方が簡単だと思いました」。これは循環論ですよね?「みんな」がJULではなくlogging-framework-Xを使用するのはなぜですか?

  5. 「他の誰もがlogging-framework-Xを使用しています」。これは、上記の特別なケースです。大多数が常に正しいとは限りません。

だから本当の大きな問題はなぜJULでないのですか?。私が見逃したものは何ですか?ロギングファサード(SLF4J、JCL)の存在理由は、複数のロギング実装が歴史的に存在しており、その理由は、私が見る限り、JULの前の時代に本当に戻っているためです。JULが完璧だったとしたら、ファサードのロギングは存在しなかったでしょうか。問題をさらに混乱させるのは、JUL自体がある程度ファサードであり、ハンドラー、フォーマッター、さらにはLogManagerさえもスワップできるようにすることです。

同じこと(ロギング)を行う複数の方法を採用するのではなく、そもそもなぜそれらが必要だったのか疑問に思わないでしょうか。(そして、それらの理由がまだ存在するかどうかを確認してください)

わかりました、これまでのところ私の研究により、JULの実際の問題であると思われるいくつかのことがわかりました。

  1. パフォーマンス。SLF4Jのパフォーマンスは他より優れていると言う人もいます。これは時期尚早の最適化の場合のようです。1秒あたり数百メガバイトをログに記録する必要がある場合、とにかく正しいパスにいるとは思えません。JULも進化しており、Java 1.4で行ったテストは真実ではなくなっている可能性があります。あなたはそれについてここで読むことができ、この修正はそれをJava 7に取り入れました。多くの人はロギングメソッドでの文字列連結のオーバーヘッドについても話します。ただし、テンプレートベースのロギングはこのコストを回避し、JULにも存在します。個人的には、テンプレートベースのロギングを実際に書くことはありません。そのために怠惰です。たとえば、JULでこれを行う場合:

    log.finest("Lookup request from username=" + username 
       + ", valueX=" + valueX
       + ", valueY=" + valueY));
    

    私のIDEは私に警告し、それを次のように変更するように許可を求めます。

    log.log(Level.FINEST, "Lookup request from username={0}, valueX={1}, valueY={2}", 
       new Object[]{username, valueX, valueY});
    

    ..もちろんそれを受け入れます。許可が与えられました!ご協力ありがとうございました。

    そのため、私は実際にそのようなステートメントを自分で書くことはありません。それはIDEによって行われます。

    パフォーマンスの問題について結論すると、JULのパフォーマンスが競合他社に比べて良くないことを示唆するものは何も見つかりませんでした。

  2. クラスパスからの設定。デフォルトのJULは、クラスパスから構成ファイルをロードできません。数行のコード、それはそうするために。これが煩わしい理由はわかりますが、解決策は短くて簡単です。

  3. 出力ハンドラーの可用性。JULには、コンソール、ファイルストリーム、ソケット、メモリの5つの出力ハンドラーが付属しています。これらは拡張することも、新しいものを書くこともできます。これは、たとえば、UNIX / Linux SyslogおよびWindowsイベントログへの書き込みである可能性があります。私は個人的にこの要件があったことも、使用されたこともありませんでしたが、なぜそれが便利な機能であるのかについては確かに関係があります。たとえば、LogbackにはSyslog用のアペンダーが付属しています。それでも私はそれを主張します

    1. 出力宛先のニーズの99.5%は、JULに標準で含まれているものでカバーされます。
    2. 特別なニーズは、他の何かの上ではなく、JULの上にあるカスタムハンドラーによって満たされる可能性があります。JULのSyslog出力ハンドラーを作成するのに、別のロギングフレームワークの場合よりも時間がかかることを示唆するものは何もありません。

見落としていることがあるのではないかと本当に心配です。JUL以外のロギングファサードとロギング実装の使用は非常に広範囲に及んでいるので、理解できないのは私だという結論に達しなければなりません。それは初めてではないでしょう、私は恐れています。:-)

では、APIをどうすればよいですか?成功してほしい。もちろん、「流れに乗って」SLF4J(最近最も人気があるようです)を実装することもできますが、私自身のために、すべてのファズを正当化する今日のJULの何が間違っているのかを正確に理解する必要がありますか?自分のライブラリにJULを選択して、自分自身を妨害することはありますか?

テスト性能

(2012年7月7日のnolan600によって追加されたセクション)

SLF4Jのパラメーター化がJULの10倍以上であるというCekiからの以下の参照があります。だから私はいくつかの簡単なテストを始めました。一見すると主張は確かに正しいです。以下は予備的な結果です(ただし、読んでください!):

  • 実行時間SLF4J、バックエンドログバック:1515
  • 実行時間SLF4J、バックエンドJUL:12938
  • 実行時間JUL:16911

上記の数値はミリ秒なので、少ないほど良いです。したがって、10倍のパフォーマンスの違いは、実際にはかなり近いです。私の最初の反応:それはたくさんです!

これがテストの中核です。ご覧のとおり、整数と文字列はループで構成されており、ログステートメントで使用されています。

    for (int i = 0; i < noOfExecutions; i++) {
        for (char x=32; x<88; x++) {
            String someString = Character.toString(x);
            // here we log 
        }
    }

(私はログステートメントにプリミティブデータタイプ(この場合はint)とより複雑なデータタイプ(この場合はString)の両方を持たせたいと思っていました。

SLF4Jのログステートメント:

logger.info("Logging {} and {} ", i, someString);

JULのログステートメント:

logger.log(Level.INFO, "Logging {0} and {1}", new Object[]{i, someString});

JVMは、実際の測定が行われる前に一度実行された同じテストで「ウォームアップ」されました。Java 1.7.03はWindows 7で使用されました。最新バージョンのSLF4J(v1.6.6)とLogback(v1.0.6)が使用されました。stdoutとstderrがnullデバイスにリダイレクトされました。

ただし、注意してください。JULはgetSourceClassName()デフォルトでソースクラス名を出力に出力しますが、Logbackは出力しないため、JULがほとんどの時間を費やしていることがわかります。リンゴとオレンジを比較しています。私はもう一度テストを行い、実際に同じものを出力するように、同様の方法でロギング実装を構成する必要があります。ただし、SLF4J + Logbackは引き続き上位に表示されると思われますが、上記の最初の数値とはかけ離れています。乞うご期待。

ところで、このテストは、SLF4JまたはLogbackを実際に使用したのが初めてでした。楽しい経験。JULは、あなたが始めているときは確かにずっと居心地が悪いです。

テストのパフォーマンス(パート2)

(2012年7月8日にnolan600によって追加されたセクション)

結局のところ、JULでパターンをどのように構成するか、つまり、ソース名が含まれているかどうかに関係なく、パフォーマンスにとってそれほど重要ではありません。私は非常に単純なパターンで試しました:

java.util.logging.SimpleFormatter.format="%4$s: %5$s [%1$tc]%n"

上記のタイミングはまったく変わりませんでした。私のプロファイラーは、getSourceClassName()これが私のパターンの一部ではない場合でも、ロガーが呼び出しに多くの時間を費やしていることを明らかにしました。パターンは関係ありません。

したがって、少なくともテスト済みのテンプレートベースのログステートメントでは、JUL(低速)とSLF4J + Logback(高速)の実際のパフォーマンスの差はおよそ10倍になるように見えるというパフォーマンスの問題について結論付けています。Cekiが言ったように。

また、SLF4JのgetLogger()呼び出しはJUL の同上よりもはるかに高価であるという別のことがわかります。(私のプロファイラーが正確である場合、95 ms vs 0.3 ms)。意味あり。SLF4Jは、基礎となるロギング実装のバインディングにしばらく時間をかける必要があります。これは私を怖がらせません。これらの呼び出しは、アプリケーションの存続期間中、いくらか珍しいはずです。堅牢性は実際のログ呼び出しにあるはずです。

最終結論

(2012年7月8日にnolan600によって追加されたセクション)

たくさんのご回答ありがとうございます。私が当初APIにSLF4Jを使用することに決めたと思っていたのとは対照的に。これは多くのこととあなたの入力に基づいています:

  1. 展開時にログの実装を柔軟に選択できます。

  2. アプリケーションサーバー内で実行した場合のJUL設定の柔軟性の欠如に関する問題。

  3. SLF4Jは、特にLogbackと組み合わせると、上記で詳しく説明したように、はるかに高速になります。これが大まかなテストであったとしても、JULよりもSLF4J + Logbackの最適化に多くの労力が費やされたと信じる理由があります。

  4. ドキュメンテーション。SLF4Jのドキュメントは、はるかに包括的で正確です。

  5. パターンの柔軟性。テストを行ったとき、JULにLogbackのデフォルトのパターンを模倣するようにしました。このパターンには、スレッドの名前が含まれています。JULはそのままではこれを実行できないことがわかりました。わかりました、今まで見逃していませんが、ログフレームワークでは見逃してはならないことだと思います。限目!

  6. 今日(または多くの)JavaプロジェクトはMavenを使用しているため、依存関係を追加することはそれほど大きな問題ではありません。これはSLF4Jに当てはまるようです。また、SLF4J jarとその仲間はサイズが小さいです。

奇妙なことに、SLF4Jで少し作業した後、JULにかなり腹を立てていました。JULでは、このようにする必要があることを今でも後悔しています。JULは完璧とはほど遠いですが、仕事をするのはちょっとです。十分に十分ではありません。Properties例として同じことが言えますが、抽象化については考えていません。そのため、人々は独自の構成ライブラリをプラグインして、何を持っているのでしょう。その理由はProperties、バーの真上にあるからだと思いますが、今日のJULにはその逆が当てはまります...過去には、存在しなかったためゼロになりました。


8
締めくくりはしませんが、このよく提示された質問は興味深いものですが、FAQを読むと境界線です。意見に基づいていない明確な一意の答えを見つけるのは難しいでしょう。
DenysSéguret2012

あなたが見逃している可能性があるのは、多くのフレームワーク作成者がJULを使用しようとするのをあきらめたことです。
DenysSéguret2012

3
7月以前の一般的なロギングフレームワークを指す場合、「logging-framework-X」という一般用語を使用すると誤解を招きます。この場合、「log4j」を使用する必要があります。SLF4Jやlogbackなどの他の人気のあるフレームワークは、julがリリースされた後、よく登場しました。
Ceki

1
@Acuariano。Nettyプロジェクトは、Reflectionを使用して、クラスパスで利用可能なロギングフレームワークをテストしています。ソースはこちらをご覧ください。を参照してくださいInternalLoggerFactory.java
peterh 2016年

1
@xenoterracideがさらに重要なのは、導入されたJava 9の更新ですjava.lang.System.Logger。これはインターフェースであり、そのフレームワークが追いつき、そのインターフェースの実装を提供している限り、必要な実際のロギングフレームワークにリダイレクトできます。モジュール化と組み合わせると、java.util.logging別のフレームワークが必要な場合、を含まないバンドルされたJREを使用してアプリケーションをデプロイすることもできます。
Holger

回答:


207

免責事項:私はlog4j、SLF4J、およびlogbackプロジェクトの創設者です。

SLF4Jを選択する客観的な理由があります。まず、SLF4Jは、エンドユーザーが自由に基礎となるロギングフレームワークを選択できるようにします。さらに、経験豊富なユーザーは、log4jを超える機能を提供するlogbackを好む傾向があり、jul はかなり遅れています。一部のユーザーには機能ごとのjulで十分な場合がありますが、それ以外の多くのユーザーにとっては不十分です。簡単に言えば、ロギングが重要な場合は、基礎となる実装としてlogbackを備えたSLF4Jを使用する必要があります。ロギングが重要でない場合は、julで問題ありません。

ただし、oss開発者は、自分のユーザーだけでなく、ユーザーの設定を考慮する必要があります。したがって、SLF4Jがjulより優れていると確信しているためはなく、現在(2012年7月)ほとんどのJava開発者がロギングAPIとしてSLF4Jを選択しているため、SLF4J 採用する必要があります。最終的に世論を気にしないことにした場合は、次の事実を考慮してください。

  1. julはJDKにバンドルされているため、julを好む人は便利です。私の知る限りでは、julを支持する他の客観的な議論はありません。
  2. あなた自身のjulの好みはまさにそれ、好みです。

したがって、一見勇敢に見える一方で、世論より「厳格な事実」を保持することは、この場合の論理的な誤りです。

それでも納得できない場合は、JB Nizetがさらに強力な議論を行います。

エンドユーザーが自分のコード、またはlog4jまたはlogbackを使用する別のライブラリに対してすでにこのカスタマイズを行っている場合を除きます。julは拡張可能ですが、logback、jul、log4jを拡張する必要があります。神は、4つの異なるログフレームワークを使用する4つのライブラリを使用するため、他のどのログフレームワークを知っているかが面倒です。SLF4Jを使用することにより、選択したものではなく、彼が望むロギングフレームワークを設定することができます。典型的なプロジェクトは、あなただけのものではなく、無数のライブラリーを使用することに注意してください

なんらかの理由でSLF4J APIが嫌いで、それを使用することで作業の楽しさが失われる場合は、必ずjulを使用してください結局のところ、julをSLF4Jリダイレクトする手段があります。

ちなみに、julのパラメーター化はSLF4Jの10倍以上遅く、結果として顕著な違いが生じます。


2
@Cekiあなたは免責事項について少し詳しく説明したいと思うかもしれませんので、log4j、slf4j、logbackプロジェクトでの現在の役割について言及しています。その理由は当然あなたの偏見を説明するためです。
–ThorbjørnRavn Andersen 2012

2
ほとんどのJava開発者がロギングAPIとしてSLF4Jを好むという主張に対する支持はありますか?
Olivier Cailloux 2016年

3
私の投稿の本質は、開発者が異なれば好みも異なり、論争の余地がないように見えることです。はい?
Ceki

1
正直なところ、Java 11(または最終的に何であれ)での2018年のベンチマーク、および非同期モードでのlog4j2に対するベンチマークを見たいです。
xenoterracide

5
ここで私はSLF4Jを使用して、午前、と私はまだ他のライブラリを使用するすべての他のロギングフレームワークに対処する必要があります。SLF4Jを使用しても、異種ロガーの問題は解決されず、悪化するだけです。xkcd.com/927
チャーリー

34
  1. java.util.loggingJava 1.4で導入されました。それ以前にロギングの用途があったため、他にも多くのロギングAPIが存在します。これらのAPIはJava 1.4より前に頻繁に使用されていたため、1.4がリリースされたときに0に下がらないだけの大きな市場シェアがありました。

  2. JULはそれほど素晴らしいものから始まったわけではなく、あなたが言及したことの多くは1.4でかなり悪く、1.5でしか良くなりませんでした(そして私も6で推測しますが、私はあまり確信がありません)。

  3. JULは、同じJVM内の構成が異なる複数のアプリケーションにはあまり適していません(相互作用してはならない複数のWebアプリケーションを考えてください)。Tomcatは、それを機能させるためにいくつかのフープをジャンプする必要があります(私が正しく理解していれば、JULを効果的に再実装します)。

  4. ライブラリが使用するロギングフレームワークに常に影響を与えることはできません。したがって、SLF4J(実際には他のライブラリーの上にある非常に薄いAPIレイヤー)を使用すると、ロギングの世界全体のある程度一貫した全体像を保つのに役立ちます(そのため、同じシステムでライブラリーロギングを維持しながら、基礎となるロギングフレームワークを決定できます)。

  5. ライブラリは簡単に変更できません。以前のバージョンのライブラリがlogging-library-Xを使用していた場合、login-library-Y(JULなど)に切り替えるのは簡単ではありません。後者が明らかに優れているとしても、そのライブラリのユーザーは誰でも学ぶ必要があります。新しいロギングフレームワークと(少なくとも)ロギングを再構成します。それは、特にそれがほとんどの人に明らかな利益をもたらさないとき、大きなノーノーです。

とは言っても、最近のJULは少なくとも他のロギングフレームワークの有効な代替手段だと思います。


1
ヨアヒムに感謝します。あなたの投稿に感謝します。あなたの(1)と(2)は私にとって単なる歴史です。ずっと前。あなたの(4)はその結果であり、私が循環論と呼ぶものになります。あなたの(3)は本当に興味深いです。多分あなたは何かに取り組んでいますか?しかし、これは、結局のところ非常に少数のアプリケーションコンテナを構築している人にのみ影響します。または何?
peterh 2012

3
まあ、歴史を無視する人はそれを繰り返す運命にあります;-)歴史はソフトウェア開発に非常に関連しています。人々は動きが速すぎず、既存のサードパーティライブラリを標準APIで置き換えるのは、標準API が少なくともサードパーティライブラリと同じくらい機能する場合にのみうまく機能ます。そして、それらは最初はしませんでした(そして、おそらくいくつかのケースではまだしていません)。
Joachim Sauer

ヨアヒム、私はあなたが言及している「間違いなくまだいくつかのケースではまだない」それらに興味があります。それは肉でなければならないことでした。既存のコードでロガーライブラリを置き換えるのは簡単で、最近は自動化できます。SLF4Jには、私の目的を証明するためのツールがあります。したがって、2002年にlog4jで記述された大規模なライブラリは、自動化されたツールを使用してほんの数分でJULに変換できると思います。(ただし、存在するかどうかはわかりません)。なぜそれが起こらないのですか?
peterh 2012

3
@ nolan6000:その語句の詳細を説明するための詳細については、私は十分に知りません。それは、私が実際に主張していることではありません。JULがサードパーティのフレームワークと同等になったとしても、慣性と既存のインフラストラクチャが切り替えられない大きな理由です。たとえば、ライブラリXがバージョン1.1でslf4jを使用した場合、1.2(または2.0)でのJULへの切り替えは、多くのユーザー(古いシステムをすでに正しく設定していて、明らかな利益を得るために再実行する必要がある)にとって大きな問題になります。 。
ヨアヒムザウアー

@ nolan6000場合でも、あなたは、歴史を気にしないライブラリあなたは、アプリケーションで使用が最も確かください。ライブラリがあなたとは異なるロギングフレームワークを使用したからといって、ライブラリを破棄する必要はありません。
–ThorbjørnRavn Andersen 2012

29

IMHO、slf4jのようなロギングファサードを使用する主な利点は、ライブラリのエンドユーザーに、エンドユーザーに選択を課すのではなく、希望する具体的なロギング実装を選択させることです。

たぶん彼はLog4jまたはLogBack(特別なフォーマッター、アペンダーなど)に時間とお金を投資しており、julを構成するのではなく、Log4jまたはLogBackを引き続き使用することを好みます。問題ありません:slf4jはそれを許可します。JULではなくLog4jを使用するのは賢明な選択ですか?多分そうでないかもしれません。しかし、あなたは気にしません。エンドユーザーが好きなものを選択できるようにします。


JBに感謝します。私の質問は、JULを彼に強制することによって、自分のライブラリのユーザー/実装者に本当に多くのことを課しているのかどうかです。たとえば、JULの標準出力ハンドラーに不満がある場合は、私が見ているように、デプロイメント時にそれらを自分用に交換できます。私はJULを拘束衣とは考えていません。他の人と同じように柔軟で拡張性があるように思えます。
peterh 2012

12
エンドユーザーが自分のコード、またはlog4jまたはLogBackを使用する別のライブラリに対してすでにこのカスタマイズを行っている場合を除きます。julは拡張可能ですが、LogBack、jul、log4jを拡張する必要があります。神は、4つの異なるロギングフレームワークを使用する4つのライブラリを使用するため、他のどのロギングフレームワークを知っているかが面倒です。slf4jを使用すると、彼が望むロギングフレームワークを設定することができます。選択したものではありません。典型的なプロジェクトは、あなただけのものではなく、無数のライブラリーを使用することを覚えておいてください。
JBニゼット2012

6

私は、あなたが思っているように、JULを使い始めました。しかし、何年もかけて、もう少し時間をかけて選んだらいいのにと思っています。

私の主な問題は、多くのアプリケーションで使用されている大量の「ライブラリ」コードがあり、すべてJULを使用していることです。これらのツールをWebサービスタイプのアプリで使用するたびに、ログが表示されなくなるか、予測できない、または奇妙な場所に移動します。

私たちの解決策は、ライブラリコードにファサードを追加することでした。つまり、ライブラリログの呼び出しは変更されず、利用可能なログメカニズムに動的にリダイレクトされました。POJOツールに含まれている場合はJULに送信されますが、Webアプリとしてデプロイされている場合はLogBackにリダイレクトされます。

私たちの後悔-もちろん-ライブラリー・コードはパラメーター化されたロギングを使用しないことですが、これは必要に応じて後付けできるようになりました。

ファサードの構築にはslf4jを使用しました。


1
slf4jディストリビューションで「リダイレクトjava.util.logging to slf4j」パッケージを使用しなかった理由は何ですか?
–ThorbjørnRavn Andersen 2012

2
実行しましたが、slf4jへの移行の主な利点は効率的なパラメーター化されたロギングであるため、ほとんど価値がありません。最初からそれを使用していたとしたら、今は何もする必要がありませんでした。
OldCurmudgeon 2012

1
私はこれがslf4jのぶら下がりの実であることに同意します。
–ThorbjørnRavn Andersen 2012

3

logback-1.1.7でslf4j-1.7.21に対してjulを実行し、SSD、Java 1.8、Win64に出力しました

1Mループの場合、julは48449ミリ秒、ログバックは27185ミリ秒実行されました。

それでも、もう少し高速でもう少し良いAPIは、3つのライブラリと800Kの価値はありません。

package log;

import java.util.logging.Level;
import java.util.logging.Logger;

public class LogJUL
{
    final static Logger logger = Logger.getLogger(LogJUL.class.getSimpleName());

    public static void main(String[] args) 
    {
        int N = 1024*1024;

        long l = System.currentTimeMillis();

        for (int i = 0; i < N; i++)
        {
            Long lc = System.currentTimeMillis();

            Object[] o = { lc };

            logger.log(Level.INFO,"Epoch time {0}", o);
        }

        l = System.currentTimeMillis() - l;

        System.out.printf("time (ms) %d%n", l);
    }
}

そして

package log;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogSLF
{
    static Logger logger = LoggerFactory.getLogger(LogSLF.class);


    public static void main(String[] args) 
    {
        int N = 1024*1024;

        long l = System.currentTimeMillis();

        for (int i = 0; i < N; i++)
        {
            Long lc = System.currentTimeMillis();

            logger.info("Epoch time {}", lc);
        }

        l = System.currentTimeMillis() - l;

        System.out.printf("time (ms) %d%n", l);
    }

}

3
のようなものを比較するのではありません。julの配列を明示的に作成するのはなぜですか?slf4jには引数が1のオーバーロードがないためだと思いlogger.info()ます。したがって、slf4jのインターフェースの欠点を補うために、julのパフォーマンスを故意に損なうことになります。代わりに、慣用的にコーディングされている方法で両方のメソッドをコーディングする必要があります。
Klitos Kyriacou

2
あなたはそれを誤解しました。追加の800Kを使用する必要はありません。コンセンサスは、非常に薄い SLF4J apiを使用する価値があるということです。それは、あなた(またはコードを1日再利用する可能性のある人)がJUL、Logback、Log4jなどの間で自由に切り替えられるためです。SLF4Jはわずか28Kです。SLF4JからJULへのブリッジ(slf4j-jdk ... jar)はわずか〜9Kです。
Riskop 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.