- PR -

RS232Cを介したデータの読み取り

1
投稿者投稿内容
とどろき
会議室デビュー日: 2006/04/19
投稿数: 3
投稿日時: 2006-04-20 19:04
はじめまして.とどろきと申します.
RS232Cを介して,RFIDのリーダライタに命令を送信して,
そのレスポンスパケットを取り込むプログラムを作成しています.

問題
RFIDリーダライタに命令を送信 → Streamを使用してレスポンスパケットを取り込む → メモリが増加して,放っておくと"OutOfMemoryError"になってしまう.

プログラム概要
@ 「ICタグのIDを読み取る」という命令を,RFIDリーダライタに送り続けます.
A 読み取った場合には,そのIDが登録してあるIDかどうかを判断します.
B 登録してあるIDの場合は,処理を実行します.
C 読み取れなかったor登録してないIDの場合には,@に戻ります.

ソース
class isoRead {
private static CommPortIdentifier ports;
private static SerialPort serialPort;
private static OutputStream out;
private static InputStream in;
private static int header = 0xXX, ..., checksum = 0xXX; //命令群

private static String temp1;

private static int i, j, read;

static void start() { //あるプログラムから呼び出され,start()から始まります
String readTag;
String arrive = "1901892146007224";
String[] leave = { "562431676007224", "432232071007224","211902261007224"}; //登録してあるID
int i, minute;
boolean bStop = true;

while (bStop) {
try {
ports = CommPortIdentifier.getPortIdentifier("COM1");

serialPort = (SerialPort) ports.open("RS232C", 1000);

serialPort.setSerialPortParams(57600, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_XONXOFF_IN
| SerialPort.FLOWCONTROL_XONXOFF_OUT);

out = serialPort.getOutputStream();
in = serialPort.getInputStream();

// RFIDリーダライタに命令を送る
CommandInventory(out);

readTag = "";
// RFIDからのレスポンスを受け取る
readTag = Inventory(in);

if (readTag != "") { //登録してあるIDであったときの処理
MFTP.ArriveFTP();
} else
for (i = 0; i <= 3; i++) {
if (readTag.equals(leave[i])) {
GFTP.LeaveFTP();
}
}
}
out.close();
in.close();
serialPort.close();

out = null;
in = null;
serialPort = null;
}
} catch (Exception e) {
System.out.println("Error:" + e.getMessage());
bStop = false;
}
}
}

static void CommandInventory(OutputStream rout) {
try {
rout.write(header);//「IDを読み取る」というコマンドを送信



rout.write(checksum);
rout.flush();

} catch (Exception e) {
System.out.println("Error:" + e.getMessage());
}
}

static String Inventory(InputStream rin) {
try {
temp1 = "";
for (i = 0; i < 23; i++) {//タグを読み取った場合には,レスポンス(23byte)が返ってくる
if (i >= 13 && i <= 20) {//レスポンスの13〜20byte目でタグのID情報を取得できる
read = rin.read();//IDを1byteずつ取ってきてint型の変数に入れる
temp1 = temp1 +Integer.toString(read);//取ってきたIDを繋げたいので,String型に変換
} else {
read = rin.read();
}

if (read == 13) {//タグを読み取れなかった場合には,2byte目の値が13となる(これはパケット全体の長さ)
for (j = 0; j < 11; j++) {//タグを読み取れなかった場合のレスポンスは13byteである.よって2byte目以降を読み取ってくる
read = rin.read();
}
break;
}
}
} catch (Exception e) {
System.out.println("Error:" + e.getMessage());
}
return temp1;
}
}

エラー内容は以下の通りです
java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start(Native Method)
at com.sun.comm.Win32SerialPort.<init>(Win32SerialPort.java:51)
at com.sun.comm.Win32Driver.getCommPort(Win32Driver.java:69)
at javax.comm.CommPortIdentifier.open(CommPortIdentifier.java:314)
at isoRead.start(isoRead.java:44)
at isoKey.main(isoKey.java:90)


"readTag = Inventory(in)"の部分をコメントアウトして,レスポンスパケットを受け取りにいかないと,メモリの使用量が受け取りに行く場合に比べ,著しく増加してしまいます.もちろん受け取る場合も,メモリ使用量が増加していきます.また,"CommandInventory(out);"の命令を送る部分をコメントアウトすると,メモリ使用量は増加しません.
あくまで私見ですが,RFIDリーダライタからのレスポンスパケットは,一度メモリ上に全て展開されているのではないかと考えています.この問題を解決する方法はありますでしょうか.

自分で試したこと
バッファに一度取り込んで,それをファイルに書き出すという方法を試してみたのですが,結果は同じでメモリ使用量が増えていきました.

環境
Windows XP
j2sdk1.4.2_11
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2006-04-21 10:18
CommPortIdentifier.open() の内部でスレッドを作ろうとして失敗しているみたいですね。
ループの外でポートをオープンしておいて再利用する方法はいかがでしょうか?
とどろき
会議室デビュー日: 2006/04/19
投稿数: 3
投稿日時: 2006-04-21 14:59
>インギ様

ご回答ありがとう御座います.

引用:

インギさんの書き込み (2006-04-21 10:18) より:
CommPortIdentifier.open() の内部でスレッドを作ろうとして失敗しているみたいですね。
ループの外でポートをオープンしておいて再利用する方法はいかがでしょうか?


上記の通り,ループの外でポートをオープンしてみたところ,メモリ使用量の増加は抑えられました.ご助言いただき,本当に助かりました.
念のため,修正済のソースを下に提示します.

try {

ports = CommPortIdentifier.getPortIdentifier("COM1");

serialPort = (SerialPort) ports.open("RS232C", 1000);

serialPort.setSerialPortParams(57600, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_XONXOFF_IN
| SerialPort.FLOWCONTROL_XONXOFF_OUT);

} catch (Exception e) {
System.out.println("Error:" + e.getMessage());
}

while (bStop) {
//while文開始
1

スキルアップ/キャリアアップ(JOB@IT)