< prev index next >

src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c

Print this page
rev 12437 : 8131168: Refactor ProcessHandleImpl_*.c and add implememtation for AIX


  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "jni.h"
  27 #include "jni_util.h"
  28 #include "java_lang_ProcessHandleImpl.h"
  29 #include "java_lang_ProcessHandleImpl_Info.h"
  30 


  31 #include <stdio.h>
  32 #include <errno.h>
  33 #include <signal.h>
  34 #include <stdlib.h>
  35 #include <unistd.h>
  36 #include <string.h>
  37 
  38 #include <sys/sysctl.h>
  39 
  40 /**
  41  * Implementations of ProcessHandleImpl functions for MAC OS X;
  42  * are NOT common to all Unix variants.
  43  */
  44 
  45 static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t pid);
  46 static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid);
  47 
  48 /*
  49  * Common Unix function to lookup the uid and return the user name.
  50  */
  51 extern jstring uidToUser(JNIEnv* env, uid_t uid);
  52 
  53 /* Field id for jString 'command' in java.lang.ProcessHandle.Info */
  54 static jfieldID ProcessHandleImpl_Info_commandID;
  55 
  56 /* Field id for jString[] 'arguments' in java.lang.ProcessHandle.Info */
  57 static jfieldID ProcessHandleImpl_Info_argumentsID;
  58 
  59 /* Field id for jlong 'totalTime' in java.lang.ProcessHandle.Info */
  60 static jfieldID ProcessHandleImpl_Info_totalTimeID;
  61 
  62 /* Field id for jlong 'startTime' in java.lang.ProcessHandle.Info */
  63 static jfieldID ProcessHandleImpl_Info_startTimeID;
  64 
  65 /* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */
  66 static jfieldID ProcessHandleImpl_Info_userID;
  67 
  68 /* static value for clock ticks per second. */
  69 static long clock_ticks_per_second;
  70 
  71 /**************************************************************
  72  * Static method to initialize field IDs and the ticks per second rate.
  73  *
  74  * Class:     java_lang_ProcessHandleImpl_Info
  75  * Method:    initIDs
  76  * Signature: ()V
  77  */
  78 JNIEXPORT void JNICALL
  79 Java_java_lang_ProcessHandleImpl_00024Info_initIDs(JNIEnv *env, jclass clazz) {
  80     CHECK_NULL(ProcessHandleImpl_Info_commandID =
  81             (*env)->GetFieldID(env, clazz, "command", "Ljava/lang/String;"));
  82     CHECK_NULL(ProcessHandleImpl_Info_argumentsID =
  83             (*env)->GetFieldID(env, clazz, "arguments", "[Ljava/lang/String;"));
  84     CHECK_NULL(ProcessHandleImpl_Info_totalTimeID =
  85             (*env)->GetFieldID(env, clazz, "totalTime", "J"));
  86     CHECK_NULL(ProcessHandleImpl_Info_startTimeID =
  87             (*env)->GetFieldID(env, clazz, "startTime", "J"));
  88     CHECK_NULL(ProcessHandleImpl_Info_userID =
  89             (*env)->GetFieldID(env, clazz, "user", "Ljava/lang/String;"));
  90 }
  91 /**************************************************************
  92  * Static method to initialize the ticks per second rate.
  93  *
  94  * Class:     java_lang_ProcessHandleImpl
  95  * Method:    initNative
  96  * Signature: ()V
  97  */
  98 JNIEXPORT void JNICALL
  99 Java_java_lang_ProcessHandleImpl_initNative(JNIEnv *env, jclass clazz) {
 100       clock_ticks_per_second = sysconf(_SC_CLK_TCK);
 101 }
 102 
 103 /*
 104  * Check if a process is alive.
 105  * Return the start time (ms since 1970) if it is available.
 106  * If the start time is not available return 0.
 107  * If the pid is invalid, return -1.
 108  *
 109  * Class:     java_lang_ProcessHandleImpl
 110  * Method:    isAlive0
 111  * Signature: (J)J
 112  */
 113 JNIEXPORT jlong JNICALL
 114 Java_java_lang_ProcessHandleImpl_isAlive0(JNIEnv *env, jobject obj, jlong jpid) {
 115     pid_t pid = (pid_t) jpid;
 116     struct kinfo_proc kp;
 117     size_t bufSize = sizeof kp;
 118 
 119     // Read the process info for the specific pid
 120     int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
 121 
 122     if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
 123         return  (errno == EINVAL) ? -1 : 0;
 124     } else {
 125         return (bufSize == 0) ?  -1 :
 126                                  (jlong) (kp.kp_proc.p_starttime.tv_sec * 1000
 127                                         + kp.kp_proc.p_starttime.tv_usec / 1000);
 128     }
 129 }
 130 
 131 /*
 132  * Returns the parent pid of the requested pid.
 133  *
 134  * Class:     java_lang_ProcessHandleImpl
 135  * Method:    parent0
 136  * Signature: (J)J
 137  */
 138 JNIEXPORT jlong JNICALL
 139 Java_java_lang_ProcessHandleImpl_parent0(JNIEnv *env,
 140                                          jobject obj,
 141                                          jlong jpid,
 142                                          jlong startTime) {
 143     pid_t pid = (pid_t) jpid;
 144     pid_t ppid = -1;
 145 
 146     if (pid == getpid()) {
 147         ppid = getppid();
 148     } else {
 149         const pid_t pid = (pid_t) jpid;
 150         struct kinfo_proc kp;
 151         size_t bufSize = sizeof kp;
 152 
 153         // Read the process info for the specific pid
 154         int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
 155         if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
 156             JNU_ThrowByNameWithLastError(env,
 157                 "java/lang/RuntimeException", "sysctl failed");
 158             return -1;
 159         }
 160         // If the buffer is full and for the pid requested then check the start
 161         if (bufSize > 0 && kp.kp_proc.p_pid == pid) {
 162             jlong start = (jlong) (kp.kp_proc.p_starttime.tv_sec * 1000
 163                                    + kp.kp_proc.p_starttime.tv_usec / 1000);
 164             if (start == startTime || start == 0 || startTime == 0) {
 165                 ppid = kp.kp_eproc.e_ppid;
 166             }
 167         }
 168     }
 169     return (jlong) ppid;
 170 }
 171 
 172 /*
 173  * Returns the children of the requested pid and optionally each parent.
 174  *
 175  * Class:     java_lang_ProcessHandleImpl
 176  * Method:    getProcessPids0
 177  * Signature: (J[J[J)I
 178  *
 179  * Use sysctl to accumulate any process whose parent pid is zero or matches.
 180  * The resulting pids are stored into the array of longs.
 181  * The number of pids is returned if they all fit.
 182  * If the parentArray is non-null, store the parent pid.
 183  * If the array is too short, excess pids are not stored and
 184  * the desired length is returned.
 185  */
 186 JNIEXPORT jint JNICALL
 187 Java_java_lang_ProcessHandleImpl_getProcessPids0(JNIEnv *env,
 188                                                  jclass clazz,
 189                                                  jlong jpid,
 190                                                  jlongArray jarray,
 191                                                  jlongArray jparentArray,
 192                                                  jlongArray jstimesArray) {
 193     jlong* pids = NULL;
 194     jlong* ppids = NULL;
 195     jlong* stimes = NULL;
 196     jsize parentArraySize = 0;
 197     jsize arraySize = 0;
 198     jsize stimesSize = 0;
 199     jsize count = 0;
 200     size_t bufSize = 0;
 201     pid_t pid = (pid_t) jpid;
 202 
 203     arraySize = (*env)->GetArrayLength(env, jarray);
 204     JNU_CHECK_EXCEPTION_RETURN(env, -1);
 205     if (jparentArray != NULL) {
 206         parentArraySize = (*env)->GetArrayLength(env, jparentArray);
 207         JNU_CHECK_EXCEPTION_RETURN(env, -1);
 208 
 209         if (arraySize != parentArraySize) {
 210             JNU_ThrowIllegalArgumentException(env, "array sizes not equal");
 211             return 0;
 212         }


 286                 count++; // Count to tabulate size needed
 287             }
 288         }
 289     } while (0);
 290 
 291     if (pids != NULL) {
 292         (*env)->ReleaseLongArrayElements(env, jarray, pids, 0);
 293     }
 294     if (ppids != NULL) {
 295         (*env)->ReleaseLongArrayElements(env, jparentArray, ppids, 0);
 296     }
 297     if (stimes != NULL) {
 298         (*env)->ReleaseLongArrayElements(env, jstimesArray, stimes, 0);
 299     }
 300 
 301     free(buffer);
 302     // If more pids than array had size for; count will be greater than array size
 303     return count;
 304 }
 305 
 306 /**************************************************************
 307  * Implementation of ProcessHandleImpl_Info native methods.
 308  */
 309 
 310 /*
 311  * Fill in the Info object from the OS information about the process.
 312  *
 313  * Class:     java_lang_ProcessHandleImpl
 314  * Method:    info0
 315  * Signature: (J)I
 316  */
 317 JNIEXPORT void JNICALL
 318 Java_java_lang_ProcessHandleImpl_00024Info_info0(JNIEnv *env,
 319                                                  jobject jinfo,
 320                                                  jlong jpid) {
 321     pid_t pid = (pid_t) jpid;
 322     getStatInfo(env, jinfo, pid);
 323     getCmdlineInfo(env, jinfo, pid);
 324 }
 325 
 326 /**
 327  * Read /proc/<pid>/stat and fill in the fields of the Info object.
 328  * The executable name, plus the user, system, and start times are gathered.
 329  */
 330 static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t jpid) {
 331     jlong totalTime;                    // nanoseconds
 332     unsigned long long startTime;       // milliseconds
 333 
 334     const pid_t pid = (pid_t) jpid;
 335     struct kinfo_proc kp;
 336     size_t bufSize = sizeof kp;
 337 
 338     // Read the process info for the specific pid
 339     int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
 340 
 341     if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
 342         if (errno == EINVAL) {
 343             return;
 344         } else {
 345             JNU_ThrowByNameWithLastError(env,
 346                 "java/lang/RuntimeException", "sysctl failed");

 347         }
 348         return;
 349     }
 350 
 351     // Convert the UID to the username
 352     jstring name = NULL;
 353     CHECK_NULL((name = uidToUser(env, kp.kp_eproc.e_ucred.cr_uid)));
 354     (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, name);
 355     JNU_CHECK_EXCEPTION(env);
 356 
 357     startTime = kp.kp_proc.p_starttime.tv_sec * 1000 +

 358                 kp.kp_proc.p_starttime.tv_usec / 1000;
 359 
 360     (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime);
 361     JNU_CHECK_EXCEPTION(env);
 362 
 363     // Get cputime if for current process
 364     if (pid == getpid()) {
 365         struct rusage usage;
 366         if (getrusage(RUSAGE_SELF, &usage) != 0) {
 367             return;
 368         }
 369         jlong microsecs =
 370             usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec +
 371             usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec;
 372         totalTime = microsecs * 1000;
 373         (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime);
 374         JNU_CHECK_EXCEPTION(env);
 375     }
 376 }
 377 
 378 /**
 379  * Construct the argument array by parsing the arguments from the sequence of arguments.
 380  */
 381 static int fillArgArray(JNIEnv *env, jobject jinfo, int nargs,
 382                         const char *cp, const char *argsEnd) {
 383     jstring str = NULL;
 384     jobject argsArray;
 385     int i;
 386 
 387     if (nargs < 1) {
 388         return 0;
 389     }
 390     // Create a String array for nargs-1 elements
 391     CHECK_NULL_RETURN((argsArray = (*env)->NewObjectArray(env,
 392             nargs - 1, JNU_ClassString(env), NULL)), -1);
 393 
 394     for (i = 0; i < nargs - 1; i++) {
 395         // skip to the next argument; omits arg[0]
 396         cp += strnlen(cp, (argsEnd - cp)) + 1;
 397 
 398         if (cp > argsEnd || *cp == '\0') {
 399             return -2;  // Off the end pointer or an empty argument is an error
 400         }
 401 
 402         CHECK_NULL_RETURN((str = JNU_NewStringPlatform(env, cp)), -1);
 403 
 404         (*env)->SetObjectArrayElement(env, argsArray, i, str);
 405         JNU_CHECK_EXCEPTION_RETURN(env, -3);
 406     }
 407     (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_argumentsID, argsArray);
 408     JNU_CHECK_EXCEPTION_RETURN(env, -4);
 409     return 0;
 410 }
 411 
 412 /**
 413  * Retrieve the command and arguments for the process and store them
 414  * into the Info object.
 415  */
 416 static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
 417     int mib[3], maxargs, nargs, i;
 418     size_t size;
 419     char *args, *cp, *sp, *np;
 420 
 421     // Get the maximum size of the arguments
 422     mib[0] = CTL_KERN;
 423     mib[1] = KERN_ARGMAX;
 424     size = sizeof(maxargs);
 425     if (sysctl(mib, 2, &maxargs, &size, NULL, 0) == -1) {
 426             JNU_ThrowByNameWithLastError(env,
 427                     "java/lang/RuntimeException", "sysctl failed");
 428         return;
 429     }
 430 
 431     // Allocate an args buffer and get the arguments
 432     args = (char *)malloc(maxargs);
 433     if (args == NULL) {
 434         JNU_ThrowOutOfMemoryError(env, "malloc failed");
 435         return;
 436     }
 437 
 438     do {            // a block to break out of on error
 439         char *argsEnd;
 440         jstring str = NULL;
 441 
 442         mib[0] = CTL_KERN;
 443         mib[1] = KERN_PROCARGS2;
 444         mib[2] = pid;
 445         size = (size_t) maxargs;
 446         if (sysctl(mib, 3, args, &size, NULL, 0) == -1) {
 447             if (errno != EINVAL) {
 448             JNU_ThrowByNameWithLastError(env,
 449                     "java/lang/RuntimeException", "sysctl failed");
 450             }
 451             break;
 452         }
 453         memcpy(&nargs, args, sizeof(nargs));
 454 
 455         cp = &args[sizeof(nargs)];      // Strings start after nargs
 456         argsEnd = &args[size];
 457 
 458         // Store the command executable path
 459         if ((str = JNU_NewStringPlatform(env, cp)) == NULL) {
 460             break;
 461         }
 462         (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, str);
 463         if ((*env)->ExceptionCheck(env)) {
 464             break;
 465         }
 466 
 467         // Skip trailing nulls after the executable path
 468         for (cp = cp + strnlen(cp, argsEnd - cp); cp < argsEnd; cp++) {
 469             if (*cp != '\0') {
 470                 break;
 471             }
 472         }
 473 
 474         fillArgArray(env, jinfo, nargs, cp, argsEnd);
 475     } while (0);
 476     // Free the arg buffer
 477     free(args);
 478 }
 479 


  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "jni.h"
  27 #include "jni_util.h"
  28 #include "java_lang_ProcessHandleImpl.h"
  29 #include "java_lang_ProcessHandleImpl_Info.h"
  30 
  31 #include "ProcessHandleImpl_unix.h"
  32 
  33 #include <stdio.h>
  34 #include <errno.h>
  35 #include <signal.h>
  36 #include <stdlib.h>
  37 #include <unistd.h>
  38 #include <string.h>
  39 
  40 #include <sys/sysctl.h>
  41 
  42 /**
  43  * Implementation of native ProcessHandleImpl functions for MAC OS X.
  44  * See ProcessHandleImpl_unix.c for more details.







  45  */
















  46 
  47 void os_initNative(JNIEnv *env, jclass clazz) {}

  48 
  49 /**
  50  * Return the uid of a process or -1 on error







































  51  */
  52 uid_t os_getUID(pid_t pid) {


  53     struct kinfo_proc kp;
  54     size_t bufSize = sizeof kp;
  55 
  56     // Read the process info for the specific pid
  57     int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
  58 
  59     if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) == 0) {






































  60         if (bufSize > 0 && kp.kp_proc.p_pid == pid) {
  61             return kp.kp_eproc.e_ucred.cr_uid;




  62         }
  63     }
  64     return (uid_t)-1;
  65 }
  66 
  67 /*
  68  * Returns the children of the requested pid and optionally each parent.
  69  *




  70  * Use sysctl to accumulate any process whose parent pid is zero or matches.
  71  * The resulting pids are stored into the array of longs.
  72  * The number of pids is returned if they all fit.
  73  * If the parentArray is non-null, store the parent pid.
  74  * If the array is too short, excess pids are not stored and
  75  * the desired length is returned.
  76  */
  77 jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
  78                     jlongArray jparentArray, jlongArray jstimesArray) {





  79     jlong* pids = NULL;
  80     jlong* ppids = NULL;
  81     jlong* stimes = NULL;
  82     jsize parentArraySize = 0;
  83     jsize arraySize = 0;
  84     jsize stimesSize = 0;
  85     jsize count = 0;
  86     size_t bufSize = 0;
  87     pid_t pid = (pid_t) jpid;
  88 
  89     arraySize = (*env)->GetArrayLength(env, jarray);
  90     JNU_CHECK_EXCEPTION_RETURN(env, -1);
  91     if (jparentArray != NULL) {
  92         parentArraySize = (*env)->GetArrayLength(env, jparentArray);
  93         JNU_CHECK_EXCEPTION_RETURN(env, -1);
  94 
  95         if (arraySize != parentArraySize) {
  96             JNU_ThrowIllegalArgumentException(env, "array sizes not equal");
  97             return 0;
  98         }


 172                 count++; // Count to tabulate size needed
 173             }
 174         }
 175     } while (0);
 176 
 177     if (pids != NULL) {
 178         (*env)->ReleaseLongArrayElements(env, jarray, pids, 0);
 179     }
 180     if (ppids != NULL) {
 181         (*env)->ReleaseLongArrayElements(env, jparentArray, ppids, 0);
 182     }
 183     if (stimes != NULL) {
 184         (*env)->ReleaseLongArrayElements(env, jstimesArray, stimes, 0);
 185     }
 186 
 187     free(buffer);
 188     // If more pids than array had size for; count will be greater than array size
 189     return count;
 190 }
 191 




















 192 /**
 193  * Use sysctl and return the ppid, total cputime and start time.
 194  * Return: -1 is fail;  zero is unknown; >  0 is parent pid
 195  */
 196 pid_t os_getParentPid(JNIEnv *env, pid_t jpid, jlong *totalTime, jlong *startTime) {


 197 
 198     const pid_t pid = (pid_t) jpid;
 199     struct kinfo_proc kp;
 200     size_t bufSize = sizeof kp;
 201 
 202     // Read the process info for the specific pid
 203     int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
 204 
 205     if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {



 206         JNU_ThrowByNameWithLastError(env,
 207             "java/lang/RuntimeException", "sysctl failed");
 208         return -1;
 209     }








 210 
 211     if (bufSize > 0 && kp.kp_proc.p_pid == pid) {
 212       *startTime = kp.kp_proc.p_starttime.tv_sec * 1000 +
 213                    kp.kp_proc.p_starttime.tv_usec / 1000;
 214     }


 215 
 216     // Get cputime if for current process
 217     if (pid == getpid()) {
 218         struct rusage usage;
 219         if (getrusage(RUSAGE_SELF, &usage) == 0) {


 220           jlong microsecs =
 221               usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec +
 222               usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec;
 223           *totalTime = microsecs * 1000;
















 224         }










 225     }
 226 
 227     return (bufSize > 0 && kp.kp_proc.p_pid == pid) ? kp.kp_eproc.e_ppid : -1;
 228 






 229 }
 230 
 231 /**
 232  * Retrieve the command and arguments for the process and store them
 233  * into the Info object.
 234  */
 235 void os_getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
 236     int mib[3], maxargs, nargs, i;
 237     size_t size;
 238     char *args, *cp, *sp, *np;
 239 
 240     // Get the maximum size of the arguments
 241     mib[0] = CTL_KERN;
 242     mib[1] = KERN_ARGMAX;
 243     size = sizeof(maxargs);
 244     if (sysctl(mib, 2, &maxargs, &size, NULL, 0) == -1) {
 245             JNU_ThrowByNameWithLastError(env,
 246                     "java/lang/RuntimeException", "sysctl failed");
 247         return;
 248     }
 249 
 250     // Allocate an args buffer and get the arguments
 251     args = (char *)malloc(maxargs);
 252     if (args == NULL) {
 253         JNU_ThrowOutOfMemoryError(env, "malloc failed");
 254         return;
 255     }
 256 
 257     do {            // a block to break out of on error
 258         char *argsEnd;
 259         jstring cmdexe = NULL;
 260 
 261         mib[0] = CTL_KERN;
 262         mib[1] = KERN_PROCARGS2;
 263         mib[2] = pid;
 264         size = (size_t) maxargs;
 265         if (sysctl(mib, 3, args, &size, NULL, 0) == -1) {
 266             if (errno != EINVAL) {
 267             JNU_ThrowByNameWithLastError(env,
 268                     "java/lang/RuntimeException", "sysctl failed");
 269             }
 270             break;
 271         }
 272         memcpy(&nargs, args, sizeof(nargs));
 273 
 274         cp = &args[sizeof(nargs)];      // Strings start after nargs
 275         argsEnd = &args[size];
 276 
 277         // Store the command executable path
 278         if ((cmdexe = JNU_NewStringPlatform(env, cp)) == NULL) {




 279             break;
 280         }
 281 
 282         // Skip trailing nulls after the executable path
 283         for (cp = cp + strnlen(cp, argsEnd - cp); cp < argsEnd; cp++) {
 284             if (*cp != '\0') {
 285                 break;
 286             }
 287         }
 288 
 289         unix_fillArgArray(env, jinfo, nargs, cp, argsEnd, cmdexe);
 290     } while (0);
 291     // Free the arg buffer
 292     free(args);
 293 }
 294 
< prev index next >