Указанный пользователем код ABEND для Java Программа в z / OS - PullRequest
1 голос
/ 17 апреля 2020

Если я установлю переменную среды в средстве запуска JZOS

EXPORT JZOS_ABEND_EXIT = 50

, а затем вызову System.exit(51) в Java коде, программа будет завершается следующим образом:

IEF450I MYPROG JAVAJVM CREATE - ABEND = S000 U3333 REASON = 00000010

Можно ли указать код завершения, например, чтобы сделать его U999 вместо U3333. Я нашел крипт c ссылку на LE abend подпрограмму 'CEE3ABD' в Как вызвать пользователя ABEND? , но был бы признателен, если бы кто-то мог указать, как вызвать эту подпрограмму из Java. Нужно ли писать код JNI и вызывать его с языка C? Или есть более простой способ?

Ответы [ 2 ]

3 голосов
/ 17 апреля 2020

Я немного поиграл и обнаружил, что для 31-битной JZOS вы также можете зарегистрировать пользовательский обработчик условий с помощью опций LE-runtime-options и использовать его для перехвата аварийного завершения U3333 и его замены на что-то другое.

К сожалению, похоже, что (в z / OS 2.3) нет способа зарегистрировать обработчик условий с помощью параметров времени выполнения в 64-битном LE.

В вашем JCL вы можете добавить параметры через DD-оператор CEEOPTS:

//CEEOPTS  DD   *              
ENVAR("JZOS_ABEND_EXIT=50")    
USRHDLR(MYHDLR)                
/*                             

В обработчике вы можете проанализировать токен LE-condition.token для сообщения CEE3250 (инициируемый пользователем выход). В этом случае вы можете позвонить в CEEGQDT, чтобы получить спецификацию abend c q_data, содержащую код abend- и код причины, чтобы вы могли идентифицировать U3333.

В случае, если вы хотите выдать другой ABEND, вы затем можно позвонить в CEE3ABD. Обратите внимание, что я только заставил его работать, вызвав CEE3ABD с CLEANUP = 0, чтобы отключить любую дальнейшую обработку условий LE. Я предполагаю, что в противном случае что-то напортачит, потому что другое условие поднято, в то время как текущий обработчик еще не завершился.

Вот мой пример, написанный на PL / I, но его также можно сделать на языке COBOL или C (или Assembler, если вы предпочитаете ...)

MYHDLR: PROC(P1,P2,P3,P4) OPTIONS(BYVALUE FETCHABLE);                  

   DCL(P1,P2,P3,P4) POINTER;                                           
/* DCL CUR_COND     CHAR(12);  */  /*P1->*/                            
   DCL TOKEN        BIN FIXED(31) BASED(P2);                           
   DCL RESULT       BIN FIXED(31) BASED(P3);                           
/* DCL NEW_COND     CHAR(12);  */  /*P4->*/                            


   DCL COND_PTR      POINTER;                                          
   DCL 1 COND_STRU   BASED(COND_PTR),                                  
          2 SEVERITY BIN FIXED(15),                                    
          2 MESSAGE  BIN FIXED(15),                                    
          2 FLAGS    BIT(8),                                           
          2 FACILITY CHAR(3),                                          
          2 ISI      BIN FIXED(31);                                    

   DCL QDATA_PTR   POINTER;                                            

   DCL 1 QDATA        BASED(QDATA_PTR),                                
         2 QCOUNT_PTR POINTER,                                         
         2 ABCODE_PTR POINTER,                                         
         2 REASON_PTR POINTER;                                         

   DCL ABCODE         BIN FIXED(31) BASED(ABCODE_PTR);                 
   DCL REASON         BIN FIXED(31) BASED(REASON_PTR);                 

   DCL MYABCODE       BIN FIXED(31);                                   
   DCL CLEANUP        BIN FIXED(31);                                   

   DCL FEEDBACK     CHAR(12);                                          

   DCL SYSPRINT     FILE;                                              
   DCL (CEEGQDT,CEE3ABD)  ENTRY OPTIONS(ASM);                          

   PUT SKIP LIST('HANDLER CALLED');                                

   /* ANALYZE CONDITION */                                         
   COND_PTR = P1;                                                  
   PUT SKIP EDIT(FACILITY,MESSAGE,SEVERITY)(A,F(4),F(4));          
   IF FACILITY = 'CEE' & MESSAGE = 3250 THEN DO;                   
      PUT SKIP LIST('ABEND ISSUED');                               
      CALL CEEGQDT(COND_STRU,QDATA_PTR,FEEDBACK);                  
      COND_PTR = ADDR(FEEDBACK); /* REUSE TOKEN STRUCTURE */       
      PUT SKIP EDIT(SEVERITY,ABCODE)(F(6),F(6));                   
      IF SEVERITY = 0 &          /* CEEGQDT CALL SUCCESSFUL */     
         ABCODE = 3333           /* ONLY HANDLE USER-ABEND U3333 */
      THEN DO;                                                     
         CLEANUP = 0;            /* NO LE-CLEANUP */               
         MYABCODE = 100;                                           
         IF REASON = 51 THEN MYABCODE = 999;                       
         CALL CEE3ABD(MYABCODE,CLEANUP);                           
      END;                                                         
   END;                                                            
   ELSE DO;                                                        
      PUT SKIP LIST('NO ABEND');                                   
      RESULT = 20; /* PERCOLATE CONDITION */                       
   END;                                                            


END;                                                               
2 голосов
/ 01 мая 2020

Я решил проблему с помощью вызова JNI. Вместо того чтобы полагаться на пользовательский обработчик выхода, я вызываю метод Abend.abend непосредственно из Java.

public class Abend {
    public static native void abend(int abcode, int reasoncode, int cleanup);
}

И C реализация:

#include <stdio.h>
#include <ctest.h>
#include "Abend.h"

#define _POSIX_SOURCE
#include <unistd.h>

JNIEXPORT void JNICALL Java_Abend_abend
  (JNIEnv * end, jclass class, jint code, jint reasoncode, jint timing) {
   /* fprintf(stderr, "values %d %d %d\n", code, reasoncode, timing);*/
   __cabend(code, reasoncode, timing);
}
...