QA@IT

Java.lang.Object.finalize() でJavaMail送信時にエンコードができない。

6324 PV

お世話になっております。

オブジェクトのファイナライザでJavaMailを利用してメール送信しようとしております。

MimeMessage objMsg=new MimeMessage(session);

このとき、
以下のように本文エンコードを施してみたのですが、
いずれもファイナライザ内では指定の通りエンコードされませんでした。

objMsg.setText("こんにちは", "ISO-2022-JP");
objMsg.setText("こんにちは", "UTF-8");
objMsg.setText(new String("こんにちは".getBytes("MS932"),"Shift_JIS"),"ISO-2022-JP");

当然、メーラで見ると文字化けを起こします。
http://qa.atmarkit.co.jp/q/1900
も試してみたのですが、現象は変わりません。
なお、通常のメソッド内で送信する場合、上記のどのコードでも問題なくエンコードされます。
また、Subjectに関しては、ファイナライザ内でも問題は発生しません。
ファイナライザ内では本文エンコードが実施されないのでしょうか?

*ちなみに、Windowsマシンですので、マシンのデフォルト文字コードにあわせて以下のコードを記述すれば、
メーラでの文字化けは防げますが。。。

objMsg.setText("こんにちは", "Windows-31J");

140224追記
Javaアプリケーション単体では発生しない模様。
Servletで実施したときのみ発生。

回答

同じメール送信コードをfinalizeメソッド内、外で呼び出す確認をしてみましたが再現できませんでした。
https://gist.github.com/yusuke/9138030

finalizeメソッド内かどうかで挙動を変えるようなJavaMailの実装はたぶんないです。finalizeメソッド内だから化ける、のではなくたまたまfinalizeメソッド内に渡っている文字列が化けているのではないでしょうか?
finalizeメソッドにブレークポイントを指定してどんな文字列が渡っているか確認してみてはいかがでしょうか。

編集 履歴 (0)
  • ご回答、ありがとうございます。
    ご提示のソースをsmtpパラメータのみ変更して実行してみました。
    本文文字列は「こんにちは」です。
    ---メッセージのソース内の本文文字列---
    main内:44GT44KT44Gr44Gh44Gv
    finalize内:grGC8YLJgr+CzQ==
    ------
    と差異が発生しました。
    -
  • これを
    http://www.it-top.biz/tools/encode.php
    にてMimeデコードしたところ、
    ---3 MIME(B)デコード ---
    main内:縺薙s縺ォ縺。縺ッ
    finalize内:こんにちは
    ------
    となりました。
    つまり、finalize内ではUTF-8にエンコードされていないのではないかと考えております。
    -
  • finalizeメソッドにブレークポイントを指定してどんな文字列が渡っているか確認してみてはいかがでしょうか。 -
  • なお、Javaアプリケーション単体での挙動確認はできておりません。
    (アンチウィルスソフトでsmtp遮断されてるとか。。。)
    以下のクラスをServletでnewしております。
    これからJavaアプリケーション単体で送信できる環境を構築します。。。
    -
  • まず、先に挙げた私の方で確認済みのコードでsmtp関連のパラメータだけ変えて再現できるか試してみてください。 -
  • お世話になっております。
    Javaアプリケーション単体で挙動確認いたしました。
    yusukeさまがおっしゃるとおり、どちらでも問題なくエンコードされておりました。
    -
  • その全く同じStaticメソッドをServletで呼び出すと、やはりファイナライザでは先ほどと同じ結果となってしまいます。
    Servletのデバッグモードで本文の文字列パラメータを確認してみましたが、特に違いはありませんでした。
    また、メールのデバッグ出力も比較してみましたが、
    本文文字列と時刻などの刹那的な情報以外に差異はありませんでした。JavaMailバージョン等にも差異はありません。
    -
  • print分でデバッグするのではなく、デバッガでアタッチしましょう。ステップインすればJavaMailの内部へどんな文字列が渡っているのかわかります。 -
  • 頂いたソースの75行目でブレイクし、eclipseの変数ビューを参照、
    MimeMessageオブジェクト内のDataHandlerオブジェクトのプロパティである"object"を比較したところ、差異はありませんでした。
    という回答で意図されていることと合っていますでしょうか。。。見方が不安。
    -
  • 実際に現象が発生する環境でブレークポイントを設定してステップインすれば違いが出るはずです。 -
  • GUIの変数の見た目では、差異が生じてないので、
    getBytes()を利用して、バイトコードをなんとか取得できないものか、、、というところでつまづいております。もう少しがんばってみます。
    -
  • やっと差異を発見しました。
    MimeMessageオブジェクト内のDataHandlerオブジェクト内に「dataContentHandler」オブジェクトがあり、
    この中に「dch」という変数があります(型不明、DataContentHandlerを継承したオブジェクトを要求)。
    -
  • この値が、
    通常:「text_plain(id=9999)」、ファイナライザ内:「null」となっておりました。
    試しに通常実行の際に件の変数を「null」に設定したところ、ファイナライザと同じ本文文字列となりました。
    「dch」はprivateのプロパティで、セッターゲッターも見当たらず、私みたいなシロートが手出し
    できるような感じではないです。^^;
    -

コメント欄でソースがのっけられないので、
回答に記述します。
詳しくは、yusukeさまの回答コメントをご覧ください。

public class GcTest {
    public GcTest() throws Throwable {
        MailTest.sendMail("コンストラクタ", "こんにちは", "from@hogehoge.com", "sendto@hogehoge.com", null, null);
    }
    public void finalize() throws Throwable {
        MailTest.sendMail("ファイナライザ", "こんにちは", "from@hogehoge.com", "sendto@hogehoge.com", null, null);
    }
}
編集 履歴 (0)
  • finalizeメソッドにブレークポイントを指定してどんな文字列が渡っているか確認してみてはいかがでしょうか。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。