执行.jar文件并不是每次都写入一个文件..可能是内存泄漏吗



我正在使用此应用程序从磅秤中获取要读取到另一个应用程序中的权重。长话短说,一旦文件存在,另一个应用程序就会读取该文件,然后删除该文件。如果我试着连续跑多次,它就没有得到重量。我不喜欢它出错或抛出异常,我只需要等待大约5分钟。我的怀疑是,当程序退出时,它是一个编写器或可能的对象句柄没有被释放。我认为JVM在运行之前必须关闭才能正常运行。有人能给我指正确的方向吗?github.com/cshort2112/dymo_s100_接口

package Model;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Init {
//Vendor ID = 0x0922
//Product ID = 0x8009
public static void main(String[] args) {
try {
UsbScale scale = UsbScale.findScale();
assert scale != null;
scale.open();
double weight = 0;
try {
while (weight == 0) {
weight = scale.syncSubmit();
}
} finally {
scale.close();
}
weight = (double)Math.round(weight * 10d) / 10d;
try {
String home = System.getProperty("user.home");
File f = new File(home + File.separator + "Documents" + File.separator + "Weight.txt");
BufferedWriter out = new BufferedWriter(new FileWriter(f));
try {
out.write(String.valueOf(weight));
} finally {
out.close();
}
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
} catch (Exception e) {
try {
String home = System.getProperty("user.home");
File f = new File(home + File.separator + "Documents" + File.separator + "Weight.txt");
BufferedWriter out = new BufferedWriter(new FileWriter(f));
try {
out.write("Error! " + e.getMessage());
} finally {
out.close();
}
} catch (IOException exception) {
System.out.println("An error occurred.");
exception.printStackTrace();
}
}
}
}

以及usbscale.java:

package Model;
import org.usb4java.*;
import javax.usb.*;
import javax.usb.event.UsbPipeDataEvent;
import javax.usb.event.UsbPipeErrorEvent;
import javax.usb.event.UsbPipeListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class UsbScale implements UsbPipeListener {
private final UsbDevice device;
private UsbInterface iface;
private UsbPipe pipe;
private final byte[] data = new byte[6];
private double finalWeight;
private Context context;
private UsbScale(UsbDevice device) {
this.device = device;
}

public static UsbScale findScale() {
try {
UsbServices services = UsbHostManager.getUsbServices();
UsbHub rootHub = services.getRootUsbHub();
// Dymo S100 Scale:
UsbDevice device = findDevice(rootHub, (short) 0x0922, (short) 0x8009);
//           // Dymo M25 Scale:
//           if (device == null) {
//               device = findDevice(rootHub, (short) 0x0922, (short) 0x8004);
//           }
if (device == null) {
return null;
}
return new UsbScale(device);
} catch (Exception e) {
try {
String home = System.getProperty("user.home");
File f = new File(home + File.separator + "Documents" + File.separator + "Weight.txt");
BufferedWriter out = new BufferedWriter(new FileWriter(f));
try {
out.write("Error! " + e.getMessage());
} finally {
out.close();
}
} catch (IOException exception) {
System.out.println("An error occurred.");
exception.printStackTrace();
}
return null;
}
}
private static UsbDevice findDevice(UsbHub hub, short vendorId, short productId) {
for (UsbDevice device : (List<UsbDevice>) hub.getAttachedUsbDevices()) {
UsbDeviceDescriptor desc = device.getUsbDeviceDescriptor();
if (desc.idVendor() == vendorId && desc.idProduct() == productId) {
return device;
}
if (device.isUsbHub()) {
device = findDevice((UsbHub) device, vendorId, productId);
if (device != null) {
return device;
}
}
}
return null;
}
public Device findDevice(short vendorId, short productId)
{
int result = LibUsb.init(context);
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to initialize libusb.", result);
// Read the USB device list
DeviceList list = new DeviceList();
result = LibUsb.getDeviceList(context, list);
if (result < 0) throw new LibUsbException("Unable to get device list", result);
try
{
// Iterate over all devices and scan for the right one
for (Device device: list)
{
DeviceDescriptor descriptor = new DeviceDescriptor();
result = LibUsb.getDeviceDescriptor(device, descriptor);
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to read device descriptor", result);
if (descriptor.idVendor() == vendorId && descriptor.idProduct() == productId) {
return device;
}
}
}
finally
{
// Ensure the allocated device list is freed
LibUsb.freeDeviceList(list, true);
}
// Device not found
return null;
}
public void open()  {
try {
context = new Context();
UsbConfiguration configuration = device.getActiveUsbConfiguration();
iface = configuration.getUsbInterface((byte) 0);
// this allows us to steal the lock from the kernel
DeviceHandle handle = new DeviceHandle();
int result = LibUsb.open( findDevice((short) 0x0922, (short) 0x8009), handle);
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to open USB device", result);
result = LibUsb.setConfiguration(handle, 0);
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to set Configuration", result);
iface.claim(usbInterface -> true);
final List<UsbEndpoint> endpoints = iface.getUsbEndpoints();
pipe = endpoints.get(0).getUsbPipe(); // there is only 1 endpoint
pipe.addUsbPipeListener(this);
pipe.open();
} catch (Exception e) {
try {
String home = System.getProperty("user.home");
File f = new File(home + File.separator + "Documents" + File.separator + "Weight.txt");
BufferedWriter out = new BufferedWriter(new FileWriter(f));
try {
out.write("Error! " + e.getMessage());
} finally {
out.close();
}
} catch (IOException exception) {
System.out.println("An error occurred.");
exception.printStackTrace();
}
}
}
public double syncSubmit() {
try {
pipe.syncSubmit(data);
return finalWeight;
} catch (Exception e) {
try {
String home = System.getProperty("user.home");
File f = new File(home + File.separator + "Documents" + File.separator + "Weight.txt");
BufferedWriter out = new BufferedWriter(new FileWriter(f));
try {
out.write("Error! " + e.getMessage());
} finally {
out.close();
}
} catch (IOException exception) {
System.out.println("An error occurred.");
exception.printStackTrace();
}
return finalWeight;
}
}

public void close() throws UsbException {
try {
pipe.close();
iface.release();
LibUsb.exit(context);
} catch (Exception e) {
try {
String home = System.getProperty("user.home");
File f = new File(home + File.separator + "Documents" + File.separator + "Weight.txt");
BufferedWriter out = new BufferedWriter(new FileWriter(f));
try {
out.write("Error! " + e.getMessage());
} finally {
out.close();
}
} catch (IOException exception) {
System.out.println("An error occurred.");
exception.printStackTrace();
}
}
}
@Override
public void dataEventOccurred(UsbPipeDataEvent upde) {
if (data[2] == 12) { //This means it is in imperial Mode
if (data[1] == 4) {
int weight = (data[4] & 0xFF) + (data[5] << 8);
int scalingFactor = data[3];
finalWeight = scaleWeight(weight, scalingFactor); //final weight, applies to both metric and imperial
}else if (data[1] == 5) {
int weight = (data[4] & 0xFF) + (data[5] << 8);
int scalingFactor = data[3];
finalWeight = scaleWeight(weight, scalingFactor)*(-1); //final weight, applies to both metric and imperial
} else if (data[1] == 2) {
finalWeight = 0;
}
} else { //This would mean it is in metric
if (data[1] == 4) {
int weight = (data[4] & 0xFF) + (data[5] << 8);
int scalingFactor = data[3];
finalWeight = (scaleWeight(weight, scalingFactor)*2.20462); //final weight, applies to both metric and imperial
} else if (data[1] == 5) {
int weight = (data[4] & 0xFF) + (data[5] << 8);
int scalingFactor = data[3];
finalWeight = (scaleWeight(weight, scalingFactor)*2.20462)*(-1); //final weight, applies to both metric and imperial
} else if (data[1] == 2) {
finalWeight = 0;
}
}
}
private double scaleWeight(int weight, int scalingFactor) {
return weight * Math.pow(10, scalingFactor);
}

@Override
public void errorEventOccurred(UsbPipeErrorEvent usbPipeErrorEvent) {
Logger.getLogger(UsbScale.class.getName()).log(Level.SEVERE, "Scale Error", usbPipeErrorEvent);
try {
String home = System.getProperty("user.home");
File f = new File(home + File.separator + "Documents" + File.separator + "Weight.txt");
BufferedWriter out = new BufferedWriter(new FileWriter(f));
try {
out.write("Error! " + usbPipeErrorEvent);
} finally {
out.close();
System.exit(0);
}
} catch (IOException exception) {
System.out.println("An error occurred.");
exception.printStackTrace();
}
}
}

感谢您提前提供任何建议!

您的异常处理很差,这意味着感兴趣的文件是在代码的许多部分中编写的,因此很难准确地缩小代码的范围。

相反,尝试这种重构可能不会解决你的问题,但会减少你需要检查的地方的数量,也许问题的位置会更清楚:

  1. 为要在Init.java:中写入的文件添加单个变量

    // Use Paths.get in older JVM
    Path f = Path.of(System.getProperty("user.home"), "Documents", "Weight.txt"); 
    
  2. 擦除UsbScale类中的所有catch块异常处理程序,并让异常离开all方法。将return null;或其他错误更改为throw new LibUsbException("some message"),以提供特定类型的问题,如UsbScale.findScaleUsbScale.findDevice中的问题。

  3. 使USBScale实现AutoCloseable,以便在尝试资源时使用

    public class UsbScale implements UsbPipeListener, AutoCloseable {
    
  4. open()中添加标志isOpened=true,并关闭逻辑,以便检查!isOpened

    public void open()  {
    isOpened = true;
    ...
    }
    private boolean isOpened = false;
    public void close() throws UsbException {
    if (!isOpened) return;
    isOpened =false;
    ...
    }
    
  5. Init因此变得更短,并且是唯一写入输出文件的地方,因此调试更容易。使用Files.writeString(f, message)而不是冗长的(和复制的(new FileWriter(f)代码块,并用以下方法处理异常:

    public static void main(String[] args) throws IOException {
    String message = "[UNKNOWN]";
    Path f = Path.of(System.getProperty("user.home"), "Documents", "Weight.txt");
    try (UsbScale scale = UsbScale.findScale()){
    // scale is NEVER NULL AT THIS POINT if exceptions are handled correctly in UsbScale.findScale()
    // assert scale != null;
    scale.open();
    double weight = 0;
    while (weight == 0) {
    weight = scale.syncSubmit();
    }
    weight = Math.round(weight * 10d) / 10d;
    message = String.valueOf(weight);
    } catch (Exception e) {
    message = "Error! " + e.getMessage();
    e.printStackTrace();
    } finally {
    Files.writeString(f, message, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
    }
    

    }

  6. 最后,当两个进程访问同一个文件时,您可能需要先写入临时文件,然后重命名为目标:

    Path tmp = Files.createTempFile(f.getParent(), "weight","tmp"); 
    Files.writeString(tmp, message, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
    Files.move(tmp, f);
    

相关内容

最新更新