1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package com.sun.akuma;
25
26 import com.sun.jna.StringArray;
27 import com.sun.jna.Memory;
28 import com.sun.jna.Native;
29 import static com.sun.jna.Pointer.NULL;
30 import com.sun.jna.ptr.IntByReference;
31
32 import java.util.*;
33 import static java.util.logging.Level.FINEST;
34 import java.util.logging.Logger;
35 import java.util.logging.Level;
36 import java.util.logging.ConsoleHandler;
37 import java.io.IOException;
38 import java.io.FileInputStream;
39 import java.io.File;
40 import java.io.ByteArrayOutputStream;
41 import java.io.RandomAccessFile;
42 import java.io.DataInputStream;
43
44 import static com.sun.akuma.CLibrary.LIBC;
45 import com.sun.akuma.CLibrary.FILE;
46
47
48
49
50
51
52 public class JavaVMArguments extends ArrayList<String> {
53 public JavaVMArguments() {
54 }
55
56 public JavaVMArguments(Collection<? extends String> c) {
57 super(c);
58 }
59
60 public void removeSystemProperty(String name) {
61 name = "-D"+name;
62 String nameeq = name+'=';
63 for (Iterator<String> itr = this.iterator(); itr.hasNext();) {
64 String s = itr.next();
65 if(s.equals(name) || s.startsWith(nameeq))
66 itr.remove();
67 }
68 }
69
70 public void setSystemProperty(String name, String value) {
71 removeSystemProperty(name);
72
73 add(1,"-D"+name+"="+value);
74 }
75
76
77
78
79
80 public void removeTail(int n) {
81 removeAll(subList(size()-n,size()));
82 }
83
84 StringArray toStringArray() {
85 return new StringArray(toArray(new String[size()]));
86 }
87
88
89
90
91 public static JavaVMArguments current() throws IOException {
92 return of(-1);
93 }
94
95
96
97
98
99
100
101 public static JavaVMArguments of(int pid) throws IOException {
102 String os = System.getProperty("os.name");
103 if("Linux".equals(os))
104 return ofLinux(pid);
105 if("SunOS".equals(os))
106 return ofSolaris(pid);
107 if("Mac OS X".equals(os))
108 return ofMac(pid);
109 if("FreeBSD".equals(os))
110 return ofFreeBSD(pid);
111
112 throw new UnsupportedOperationException("Unsupported Operating System "+os);
113 }
114
115 private static JavaVMArguments ofLinux(int pid) throws IOException {
116 pid = resolvePID(pid);
117
118 String cmdline = readFile(new File("/proc/" + pid + "/cmdline"));
119 JavaVMArguments args = new JavaVMArguments(Arrays.asList(cmdline.split("\0")));
120
121
122 args.removeSystemProperty(Daemon.class.getName());
123 args.removeSystemProperty(NetworkServer.class.getName()+".mode");
124 return args;
125 }
126
127 private static int resolvePID(int pid) {
128 if(pid==-1) pid=LIBC.getpid();
129 return pid;
130 }
131
132 private static JavaVMArguments ofSolaris(int pid) throws IOException {
133
134
135 boolean areWe64 = "64".equals(System.getProperty("sun.arch.data.model"));
136
137 pid = resolvePID(pid);
138 RandomAccessFile psinfo = new RandomAccessFile(new File("/proc/"+pid+"/psinfo"),"r");
139 try {
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 psinfo.seek(8);
178 if(adjust(psinfo.readInt())!=pid)
179 throw new IOException("psinfo PID mismatch");
180
181
182
183
184
185
186
187
188
189
190
191
192 psinfo.seek(areWe64?0xEC:0xBC);
193 int argc = adjust(psinfo.readInt());
194 long argp = areWe64?adjust(psinfo.readLong()):to64(adjust(psinfo.readInt()));
195 if(LOGGER.isLoggable(FINEST))
196 LOGGER.finest(String.format("argc=%d,argp=%X",argc,argp));
197
198 File asFile = new File("/proc/" + pid + "/as");
199 if (areWe64) {
200
201
202
203
204 FILE fp = LIBC.fopen(asFile.getPath(),"r");
205 try {
206 JavaVMArguments args = new JavaVMArguments();
207 Memory m = new Memory(8);
208 for( int n=0; n<argc; n++ ) {
209
210 seek64(fp,argp+n*8);
211 if(LOGGER.isLoggable(FINEST))
212 LOGGER.finest(String.format("Seeked to %X",LIBC.ftell(fp)));
213
214 m.setLong(0,0);
215 LIBC.fread(m,1,8,fp);
216 long p = m.getLong(0);
217
218 args.add(readLine(fp, p, "argv["+ n +"]"));
219 }
220 return args;
221 } finally {
222 LIBC.fclose(fp);
223 }
224 } else {
225 RandomAccessFile as = new RandomAccessFile(asFile,"r");
226 try {
227 JavaVMArguments args = new JavaVMArguments();
228 for( int n=0; n<argc; n++ ) {
229
230 as.seek(argp+n*4);
231 int p = adjust(as.readInt());
232
233 args.add(readLine(as, p, "argv["+ n +"]"));
234 }
235 return args;
236 } finally {
237 as.close();
238 }
239 }
240 } finally {
241 psinfo.close();
242 }
243 }
244
245
246
247
248
249
250
251 private static void seek64(FILE fp, long upos) {
252 LIBC.fseek(fp,0,0);
253 while(upos<0) {
254 long chunk = Long.MAX_VALUE;
255 upos -= chunk;
256 LIBC.fseek(fp,chunk,1);
257 }
258 LIBC.fseek(fp,upos,1);
259 }
260
261
262
263
264
265 private static int adjust(int i) {
266 if(IS_LITTLE_ENDIAN)
267 return (i<<24) |((i<<8) & 0x00FF0000) | ((i>>8) & 0x0000FF00) | (i>>>24);
268 else
269 return i;
270 }
271
272 private static long adjust(long i) {
273 if(IS_LITTLE_ENDIAN)
274 return (i<<56)
275 | ((i<<40) & 0x00FF000000000000L)
276 | ((i<<24) & 0x0000FF0000000000L)
277 | ((i<< 8) & 0x000000FF00000000L)
278 | ((i>> 8) & 0x00000000FF000000L)
279 | ((i>>24) & 0x0000000000FF0000L)
280 | ((i>>40) & 0x000000000000FF00L)
281 | (i>>56);
282 else
283 return i;
284 }
285
286
287
288
289 private static long to64(int i) {
290 return i&0xFFFFFFFFL;
291 }
292
293 private static String readLine(RandomAccessFile as, int p, String prefix) throws IOException {
294 if(LOGGER.isLoggable(FINEST))
295 LOGGER.finest(String.format("Reading %s at %X",prefix,p));
296
297 as.seek(to64(p));
298 ByteArrayOutputStream buf = new ByteArrayOutputStream();
299 int ch,i=0;
300 while((ch=as.read())>0) {
301 if((++i)%100==0 && LOGGER.isLoggable(FINEST))
302 LOGGER.finest(prefix +" is so far "+buf.toString());
303
304 buf.write(ch);
305 }
306 String line = buf.toString();
307 if(LOGGER.isLoggable(FINEST))
308 LOGGER.finest(prefix+" was "+line);
309 return line;
310 }
311
312 private static String readLine(FILE as, long p, String prefix) throws IOException {
313 if(LOGGER.isLoggable(FINEST))
314 LOGGER.finest(String.format("Reading %s at %X",prefix,p));
315
316 seek64(as,p);
317 Memory m = new Memory(1);
318 ByteArrayOutputStream buf = new ByteArrayOutputStream();
319 int i=0;
320 while(true) {
321 if(LIBC.fread(m,1,1,as)==0) break;
322 byte b = m.getByte(0);
323 if(b==0) break;
324
325 if((++i)%100==0 && LOGGER.isLoggable(FINEST))
326 LOGGER.finest(prefix +" is so far "+buf.toString());
327
328 buf.write(b);
329 }
330 String line = buf.toString();
331 if(LOGGER.isLoggable(FINEST))
332 LOGGER.finest(prefix+" was "+line);
333 return line;
334 }
335
336
337
338
339 private static String readFile(File f) throws IOException {
340 ByteArrayOutputStream baos = new ByteArrayOutputStream();
341 FileInputStream fin = new FileInputStream(f);
342 try {
343 int sz;
344 byte[] buf = new byte[1024];
345
346 while((sz=fin.read(buf))>=0) {
347 baos.write(buf,0,sz);
348 }
349
350 return baos.toString();
351 } finally {
352 fin.close();
353 }
354 }
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374 private static JavaVMArguments ofMac(int pid) {
375
376 final int CTL_KERN = 1;
377 final int KERN_ARGMAX = 8;
378 final int KERN_PROCARGS2 = 49;
379 final int sizeOfInt = Native.getNativeSize(int.class);
380 IntByReference _ = new IntByReference();
381
382
383 IntByReference argmaxRef = new IntByReference(0);
384 IntByReference size = new IntByReference(sizeOfInt);
385
386
387
388 if(LIBC.sysctl(new int[]{CTL_KERN,KERN_ARGMAX},2, argmaxRef.getPointer(), size, NULL, _)!=0)
389 throw new UnsupportedOperationException("Failed to get kernl.argmax: "+LIBC.strerror(Native.getLastError()));
390
391 int argmax = argmaxRef.getValue();
392 LOGGER.fine("argmax="+argmax);
393
394 class StringArrayMemory extends Memory {
395 private long offset=0;
396
397 StringArrayMemory(long l) {
398 super(l);
399 }
400
401 int readInt() {
402 int r = getInt(offset);
403 offset+=sizeOfInt;
404 return r;
405 }
406
407 byte peek() {
408 return getByte(offset);
409 }
410
411 String readString() {
412 ByteArrayOutputStream baos = new ByteArrayOutputStream();
413 byte ch;
414 while((ch = getByte(offset++))!='\0')
415 baos.write(ch);
416 return baos.toString();
417 }
418
419 void skip0() {
420
421 while(getByte(offset)=='\0')
422 offset++;
423 }
424 }
425 StringArrayMemory m = new StringArrayMemory(argmax);
426 size.setValue(argmax);
427 if(LIBC.sysctl(new int[]{CTL_KERN,KERN_PROCARGS2,resolvePID(pid)},3, m, size, NULL, _)!=0)
428 throw new UnsupportedOperationException("Failed to obtain ken.procargs2: "+LIBC.strerror(Native.getLastError()));
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471 JavaVMArguments args = new JavaVMArguments();
472 int nargs = m.readInt();
473 m.readString();
474 for( int i=0; i<nargs; i++) {
475 m.skip0();
476 args.add(m.readString());
477 }
478
479
480
481
482
483
484 return args;
485 }
486
487 private static JavaVMArguments ofFreeBSD(int pid) {
488
489 final int CTL_KERN = 1;
490 final int KERN_ARGMAX = 8;
491 final int KERN_PROC = 14;
492 final int KERN_PROC_ARGS = 7;
493
494 IntByReference _ = new IntByReference();
495 IntByReference sysctlArgMax = new IntByReference();
496 IntByReference size = new IntByReference();
497
498 size.setValue(4);
499 if( LIBC.sysctl(new int[]{CTL_KERN, KERN_ARGMAX}, 2, sysctlArgMax.getPointer(), size, NULL, _) != 0)
500 throw new UnsupportedOperationException("Failed to sysctl kern.argmax");
501
502 int argmax = sysctlArgMax.getValue();
503 Memory m = new Memory(argmax);
504 size.setValue(argmax);
505
506 if( LIBC.sysctl(new int[]{CTL_KERN,KERN_PROC, KERN_PROC_ARGS, resolvePID(pid)}, 4, m, size, NULL, _) != 0)
507 throw new UnsupportedOperationException("");
508
509 ByteArrayOutputStream baos = new ByteArrayOutputStream();
510 ArrayList<String> lArgs = new ArrayList<String>();
511 byte ch;
512 int offset = 0;
513 while(offset < size.getValue()){
514 while((ch = m.getByte(offset++))!='\0')
515 baos.write(ch);
516 lArgs.add(baos.toString());
517 baos.reset();
518 }
519
520 return new JavaVMArguments(lArgs);
521 }
522
523
524 private static final boolean IS_LITTLE_ENDIAN = "little".equals(System.getProperty("sun.cpu.endian"));
525
526 private static final Logger LOGGER = Logger.getLogger(JavaVMArguments.class.getName());
527
528 public static void main(String[] args) throws IOException {
529
530 System.out.println("sun.arch.data.model="+System.getProperty("sun.arch.data.model"));
531 System.out.println("sun.cpu.endian="+System.getProperty("sun.cpu.endian"));
532
533 LOGGER.setLevel(Level.ALL);
534 ConsoleHandler handler = new ConsoleHandler();
535 handler.setLevel(Level.ALL);
536 LOGGER.addHandler(handler);
537
538 if (args.length==0)
539 System.out.println(current());
540 else {
541 for (String arg : args) {
542 System.out.println(of(Integer.valueOf(arg)));
543 }
544 }
545 }
546 }