0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

XamarinバインドプロジェクトでJARなどをバインドする際、Javaのファイナライザが含まれる場合の対処法。

Last updated at Posted at 2021-06-11

Javaでは、finalizeという名前の関数は「ファイナライザ」という特別な関数です。ファイナライザはクラスの後始末を行うために存在するが、いつ呼び出されるかわからない、また、呼び出されないこともあるらしく、「何かを積極的におこなう場所」ではありません。基本的に使用は推奨されてない、らしいです。

C#では同じような目的で「デストラクタ」があります。C#でデストラクタはクラス名に「~」をつけて宣言しますが、内部的には「Finalize」という関数名に変換されます。そのため、「Finalize」という関数名を使用すると、以下のような警告やエラーが出ます。

  • 「void Finalize()」という関数を作成すると「デストラクタを宣言しようとしましたか?」警告が出ます。
  • 「override void Finalize()」という関数を作成すると「Finalizeをオーバーライドしないでください。代わりにデストラクタを提供してください。」エラーが出ます。

何が問題か

XamarinバインドプロジェクトでJARをバインドする際、JARの中にファイナライザが含まれていると、Javaの「finalize」がC#の「Finalize」という関数名となってエラーが出てしまう、という問題が発生します。

本来あるべき姿としては、「Javaのfinalizeという関数名をC#のデストラクタに変換してほしい」のですが、そうはなりません。

Xamarinバインドプロジェクトでは、ビルド時エラーが発生した場合、「Metadata.xml」を編集することで、変換の方法を細かく指示することにより、エラーを回避することができます。それでは、今回、「Metadata.xml」でどのように指定すればよいか?ネットで検索したところ、いい方法はないらしい。

案1.消してしまえばいい説

ファイナライザは使用すべきでないのだから、消してしまっても問題ない、という考えのようです。

<remove-node path="/api/package[@name='your.package.name']/class[@name='Proper.ClassName']/method[@name='finalize' and count(parameter)=0]" />

案2.強引におきかえる派

Javaの

protected final void finalize()

という関数名は、通常なら

protected override sealed unsafe void Finalize()

に変換されてエラーになるが、無理やり

unsafe /**/ ~FooIterator()

というデストラクタにしています。なかなかすごい手です。

<attr path="/api/package[@name='com.company.api']/class[@name='FooIterator']/method[@name='finalize']" name="managedName">~FooIterator</attr>
<attr path="/api/package[@name='com.company.api']/class[@name='FooIterator']/method[@name='finalize']" name="visibility"></attr>
<attr path="/api/package[@name='com.company.api']/class[@name='FooIterator']/method[@name='finalize']" name="managedReturn">/**/</attr>

案3.自分で見つけた方法。

まずはビルドします。当然エラーになります。以下のようにエラー一覧が表示されます。
image.png

「エラー一覧」ウインドウからエラーが発生したダブルクリックしてエラー箇所を表示します。

image.png

Finalizeが関数名です。赤波線で「ここがエラーだよ」と教えてくれています。このソースコードを直接変更します。この例だと、たとえば今回はEventクラスのデストラクタですので、関数名をFinalizeから「~Event」に変更します。「protected override sealed」「void」は不要なので削除します。

image.png

このように変更後、「ビルド」を選択すれば、問題なくビルドできました。ただし「リビルド」や「クリーン」を選択してはいけません。「リビルト」を選択すると、デストラクタがもとのファイナライザに戻ってしまします。

どれがベストか?

  • 実際は案1で問題になる事はないと思われます。
  • しかし、本来あるべき姿としては、案2か案3です。案3はリビルドしたらエラーになるため、現実的には案2が最適ではないか思います。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?