-1

我正在使用 Epson_JavaPOS_ADK_11414_for_Linux_x64 来安装带有 pcs 的 JavaPOS(sh installJavaPOSFull-64.sh

我在不同的shell中一个接一个地运行这个程序,第二个进程由于某种原因崩溃了:

import jpos.JposException;
import jpos.POSPrinter;
import jpos.util.JposPropertiesConst;

import java.time.Duration;
import java.time.Instant;

public class POSPrinterClaimTest {
  static POSPrinter posPrinter;

  private static Boolean isOpen = false;
  private static Boolean isClaimed = false;
  private static Boolean isEnabled = false;



  static {
    System.setProperty(
        JposPropertiesConst.JPOS_POPULATOR_FILE_PROP_NAME, "jpos.xml");
  }

  public static void main(String[] args) {
    try {
      posPrinter = new POSPrinter();
      Instant start = Instant.now();
      Instant finish = null;
      Long timeElapsed = null;
      openConnection("POSPrinter1");
      finish = Instant.now();
      timeElapsed = Duration.between(start, finish).toMillis();
      System.out.println("Time taken to connect : " + timeElapsed.toString());
      Thread.sleep(100000L);
      terminate();
      System.out.println("terminated from try block");
    } catch (JposException | InterruptedException e) {
      e.printStackTrace();
      try {
        terminate();
        System.out.println("terminated from catch block");
        Thread.sleep(5000);
      } catch (JposException | InterruptedException jposException) {
        jposException.printStackTrace();
      }
    } catch(Throwable t){
      t.printStackTrace();
    } finally {
      posPrinter = null;
    }
  }

  private static void openConnection(String printerName) throws JposException {
    try {

      String printerNamesss = printerName;
      /**
       * open the printer object according to the device logical name defined in jpos.xml
       */
      posPrinter.open(printerName);
      isOpen = true;
      System.out.println("opened");
      /**
       * Get the exclusive control right for the opened device.
       * Then the device is disable from other application.
       * */
      posPrinter.claim(3000);
      isClaimed = true;
      System.out.println("claimed");
      /**
       *  enable the device for input and output
       */
      posPrinter.setDeviceEnabled(true);
      isEnabled = true;
      System.out.println("enabled");

    } catch (JposException jposException) {
      System.out.println("jpos exception in open : " + jposException.getMessage());
      throw jposException;
    } catch(Throwable t) {
      System.out.println("unknown throwable open: " + t.getMessage());
    }
  }


  public static void terminate() throws JposException {
    try {
        if(isOpen && isClaimed) {
          posPrinter.clearOutput();
          System.out.println("cleared output");
        }

        if(isEnabled) {
          posPrinter.setDeviceEnabled(false);
          isEnabled = false;
          System.out.println("setDeviceEnabled false");
        }

        if(isClaimed) {
          posPrinter.release();
          isClaimed = false;
          System.out.println("released");
        }

        if(isOpen) {
          posPrinter.close();
          isOpen = false;
          System.out.println("closed");
        }
    } catch (JposException jposException) {
      jposException.printStackTrace();
      throw jposException;
    } catch(Throwable t) {
      System.out.println("unknown throwable terminate: " + t.getMessage());
    }
  }
}


第一个过程输出

opened
claimed
enabled
Time taken to connect : 7928 --> now I start the second process.
cleared output
setDeviceEnabled false
released
closed
terminated from try block

第二道工序输出

opened
jpos exception in open : The port is already open.
jpos.JposException: The port is already open.
    at jp.co.epson.upos.core.v1_14_0001.pntr.CommonUPOSExceptionCreator.createJposException(CommonUPOSExceptionCreator.java:138)
    at jp.co.epson.upos.core.v1_14_0001.pntr.CommonUPOSExceptionCreator.createJposException(CommonUPOSExceptionCreator.java:99)
    at jp.co.epson.upos.core.v1_14_0001.pntr.CommonPrinterService.openPort(CommonPrinterService.java:3341)
    at jp.co.epson.upos.core.v1_14_0001.pntr.CommonPrinterService.claim(CommonPrinterService.java:3103)
    at jpos.BaseJposControl.claim(Unknown Source)
    at POSPrinterClaimTestThreads.openConnection(POSPrinterClaimTestThreads.java:73)
    at POSPrinterClaimTestThreads.test(POSPrinterClaimTestThreads.java:36)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
closed
terminated from catch block
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f43880ea9df, pid=12119, tid=0x00007f43690b0700
#
# JRE version: OpenJDK Runtime Environment (8.0_252-b09) (build 1.8.0_252-b09)
# Java VM: OpenJDK 64-Bit Server VM (25.252-b09 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C  [libethernetio31.so+0x1f9df]  CCommonPort::PortEvent(unsigned int, unsigned int, unsigned int*, unsigned int, unsigned char*)+0xf
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /POSPrinterTest/JavaPOS/hs_err_pid12119.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#
Aborted

如果你看到第二个进程抛出一个 JposException,然后启动它的 catch 并关闭连接。然后它突然崩溃而不是睡5秒。

有什么帮助吗?

4

2 回答 2

1

在与 EPSON 团队讨论了这个问题后,他们能够使用新的 libepsonjpos.so 和 epsonjpos.jar 来解决这个问题

它为我解决了两个问题:

  1. 帖子中的原始索赔问题 - 使用最新的 libepsonjpos.so 后解决
  2. 非安装模式下单进程多线程打印(No-SetupPOS-insall)
    • 爱普生团队说要在所有线程中同步 POSPrinter.open() 并使用他们的修复更新 epsonjpos.jar

爱普生团队对这个问题的一些引用。

多线程问题 - “更改历史记录已应用的修复是在设备共享逻辑中。仅影响 lite 模式(No-SetupPOS 版本)不同的对象被错误地假设为相等。因此只使用了第一个连接的打印机. 修复纠正了这种比较逻辑。

索赔问题 - “我们很高兴能为您提供帮助。至于问题的背景。非安装模式下的多进程使用是我们 JavaPOS ADK 的一个极端案例。在您的帮助下,我们可以改进我们的测试用例。”

爱普生团队表示,他们将在下一个版本中发布补丁。

于 2021-03-10T11:27:02.937 回答
0

看来JavaPOS Service Object的独占控制处理效果不好。

您应该得到一个超时错误,而不是端口已经打开的错误。

但是,您的程序也很糟糕。
一次尝试,捕获的范围太广了。

JposException 采取异常的形式,但它实际上只是一个错误代码通知。
仅仅因为发出 JposException 信号并不意味着它崩溃。
大多数情况下,如果您消除错误原因并重试,它将起作用。

要正确,请尝试捕获每个方法调用和属性访问。

Epson_JavaPOS_ADK 示例程序应该是这样制作的。
请编写与示例程序相同的代码。


此外:

你看到的不一样吗?
对于每个方法和属性,它会尝试以小单元捕获,并且不会通过 throw 将其传播到顶部。
我的一些来源是:

来自“Epson_JavaPOS_ADK_11414_for_Linux_x64\Sample\Samples\Printer\PrinterSample_Step15\src\printersample_step15\Step15Frame.java”

// JavaPOS's code for Step7
// Set OutputCompleteEvent listener
ptr.addOutputCompleteListener(this);
// JavaPOS's code for Step7--END

// JavaPOS's code for Step10
try {
    //Open the device.
    //Use the name of the device that connected with your computer.
    ptr.open("POSPrinter");

}
catch(JposException ex){
    JOptionPane.showMessageDialog(this, "This device has not been registered, or cannot use.",
            "",JOptionPane.WARNING_MESSAGE);
    //Nothing can be used.
    changeButtonStatus();
    return;
}

try {
    //Get the exclusive control right for the opened device.
    //Then the device is disable from other application.
    ptr.claim(1000);
    bCoverSensor = ptr.getCapCoverSensor();
}
catch(JposException ex){
    JOptionPane.showMessageDialog(this, "Fails to get the exclusive access for the device.",
            "",JOptionPane.WARNING_MESSAGE);
    //Nothing can be used.
    changeButtonStatus();
    return;
}

从评论和发布中提取情况:

那么,Claim 报告的错误可能是错误的,那么为什么不联系 EPSON 支持以提供有关这种情况的详细信息呢?

来自 OP:

已经这样做了,但我们不知道他们是否会回复。所以试图在这里找到答案;某处。:D

来自 OP:

我在单个进程中运行相同的程序,并在两个脉冲中使用多个线程。正如你所说,我现在确实收到了超时错误。只有在不同的进程场景中,我才会崩溃

如果是这样,可能是JavaPOS服务对象的进程间独占控制有问题。这就是问题所在,但正如我之前评论的那样,崩溃可能是异常结束时的清理问题。当 Claim 方法发生异常时,不要通过传播异常来结束进程,而是调用 Close 方法并尝试其他清理以正常结束。

来自 OP:

我在声明捕获块中编写了 posPrinter.close()。当使用两个进程单线程时,它可以工作并且崩溃频率显着降低。事故仍然发生了一两次。但是在两个进程中,每个进程都有 10 个线程试图声明打印机,导致一个进程能够声明,而另一个进程崩溃。try{ posPrinter.claim(3000); } catch(JposException ex) { posPrinter.close();}

看来EPSON的JavaPOS服务对象的独占控制问题可能仍然存在。请根据此类调查信息向 EPSON 进行额外查询。

于 2020-09-05T21:10:51.763 回答