في Java، هل هناك طريقة للحصول على معلمات سطر الأوامر حتى لو لم يحفظها main()؟

StackOverflow https://stackoverflow.com/questions/1058531

  •  21-08-2019
  •  | 
  •  

سؤال

لدينا برنامج به main() يقوم بتحليل CLPs معينة ولكنه لا يحفظها في أي مكان.لدي بعد ذلك رمز البرنامج الإضافي الخاص بي الذي يحتاج إلى الوصول إلى CLPs الأصلية (حتى أتمكن من إرسال المزيد من المعلمات) له.ومع ذلك، لا أستطيع تغيير main()

رأيت أنه من الواضح أن هناك طريقة للقيام بذلك في C#, ، أنا أبحث عن حل Java مكافئ على Linux.

تحديث:من الواضح أنني على دراية بكيفية عمل main().لسوء الحظ، لا يمكنني تغيير التطبيق الحالي أو طريقة استدعائه (باستثناء CLPs).لا يمكنني الوصول إلا عبر رمز البرنامج الإضافي لوضع الحماية.سؤالي هو ما إذا كانت هناك طريقة للحصول على سطر الأوامر (بدلاً من متغيرات البيئة باستخدام -D) التي تم استدعاء JVM بها.

هل كانت مفيدة؟

المحلول

وبصرف النظر عن القيام بذلك بشكل رئيسي بطريقة ما، أعتقد أن الخيار الآخر الوحيد الذي لديك هو النزول إلى مستوى نظام التشغيل وتنفيذ بعض الأوامر للحصول على الوسائط.

في نظام التشغيل Linux، يتم تخزين وسيطات سطر cmd الخاصة بالعملية الجارية في /بروك/معرف المنتج/كمدلين

لذا، للحصول عليها، سيتعين عليك العثور على معرف العملية.انظر هنا:

كيف يمكن لبرنامج Java الحصول على معرف العملية الخاص به؟

ثم استخدم هذا مفتوحا /بروك/معرف المنتج/كمدلين وتحليلها.تنسيق هذا الملف ومثال في C هنا:

http://www.unix.com/unix-advanced-expert-users/86740-retriving-command-line-arguments-partcular-pid.html

قد يكون من الأفضل تجميع هاتين المكالمتين في برنامج نصي Shell واحد تستدعيه من Java.

يرجى ملاحظة أن هذا سيكون غير محمول على الإطلاق وهو مخترق بعض الشيء.ولكن إذا كانت الاحتياجات لا بد منها ...

نصائح أخرى

والحل سهل مرة واحدة كنت أدرك أن الوسيلة الرئيسية جاوة هو مجرد أسلوب ثابت آخر أن يأخذ مجموعة سلسلة كوسيطة.

وإنشاء فئة جديدة الذي يخزن CLPs، ثم يدعو الطبقة القديمة. في وقت لاحق، يمكنك الوصول إلى CLPs باستخدام فئة جديدة:

import NotToBeChangedMainClass;

public MyMainClass {
  public static final String[] ARGUMENTS;
  public static void main(String ... args) {
    ARGUMENTS = args;
    NotToBeChangedMainClass.main(args);
  }

و}

وأخيرا، التغيير أيا كان المتصل خارجي (مثل أي ملفات دفعة) لاستخدام MyMainClass بدلا من NotToBeChangedMainClass. إذا كنت تستخدم الجرار runable أو شيئا من هذا القبيل، وهذا يتطلب تغيير ملف التكوين المناسب.

إنشاء الطبقة الرئيسية الخاصة بك. حفظ الحجج. استدعاء main القديمة.

قد يكون من الأسهل استخدام System.getProperty و-Dkey=value على سطر الأوامر (قبل اسم الفئة الرئيسي أو -jar).

في حال لم يكن لديك اختيار أي لديك على الإطلاق الإبقاء على جميع أسماء فئة الحالية مع اسمهم المحدد (<لأ href = "https://stackoverflow.com/questions/1058531/in-java-is -هناك واحد في الاتجاه إلى الحصول على رأس سطر الأوامر المعلمات، وحتى اذا-الرئيسي-ديدن / 1058647 # 1058647 "> كما جاء في تعليقك لإجابتي السابقة)، ثم لديك للذهاب مع AspectJ.

ودعونا النظر لدينا هذه الفئة:

public class UnmodifyableClassWithMain {
  public static void main(String[] args) {
    System.out.println("In main");
    new ClassUsingArgumentRegistry();
  }
}

أولا، تحتاج إلى شيء أن يحمل وسائط سطر الأوامر. وسوف تستخدم فئة بسيطة مع حقل ثابت البساطة:

public class ArgumentRegistry {
  public static String[] ARGS;
}

وبعد ذلك، تحتاج لك تعريف الجانب التي تعترض المكالمات إلى الرئيسية ومخازن الحجج.

public aspect StoreArgumentsOfMain {

  /**
   * This pointcut intercepts all calls to methods called main with a string array as
   * argument.
   */
  pointcut mainMethod(String[] arguments): execution(void main(String[])) && args(arguments);

  /**
   * Before the original main method gets called, store the arguments in the registry.
   */
  before(String[] arguments): mainMethod(arguments) {
    System.out.println("Storing arguments");
    ArgumentRegistry.ARGS = arguments;
  }

}

لتحاول بها، وأنا أيضا خلق ClassUsingArgumentRegistry:

public class ClassUsingArgumentRegistry {

  public ClassUsingArgumentRegistry() {
    System.out.println("Arguments: " + java.util.Arrays.toString(ArgumentRegistry.ARGS));
  }

}

وهذا كل شيء. إذا أنا تمكين النسيج وقت الترجمة AspectJ وتشغيل النتيجة باستخدام "جافا UnmodifyableClassWithMain فو بار الباز"، وأحصل على الانتاج follwing:

Storing arguments
In main
Arguments: [foo, bar, baz]

لاحظ أن هذا الحل هو محدود جدا كما باقتطاع لينكس سطر الأوامر أنه يوفر. في كثير من الأحيان يكون أسطر الأوامر جافا classpaths طويلة جدا، وهذا هو مشكلة حقيقية جدا.

وهنا هو كود جافا تنفيذ الإجابة التي قدمها Pablojim.

package test;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Test {
  public static List<String> getLinuxCmdline(int maxBytesToRead) throws IOException {
    List<String> result = new ArrayList<>();
    String pid = new File("/proc/self").getCanonicalFile().getName();
    File cmdlineFile = new File("/proc/" + pid + "/cmdline");
    final int growBy = 1024;
    try (FileInputStream is = new FileInputStream(cmdlineFile);) {
      byte[] data = new byte[Math.min(growBy, maxBytesToRead)];
      int totalRead = 0; 
      while (totalRead < maxBytesToRead) {
        int read = is.read(data, totalRead, data.length - totalRead);
        if (read > 0) {
          totalRead += read;
          if (data.length == totalRead) {
            data = Arrays.copyOf(data, Math.min(data.length + growBy, maxBytesToRead));
          }
        } else {
          break;
        }
      }
      int start = 0;
      int scan = 0;
      while (scan < totalRead) {
        if (data[scan] == 0) {
          result.add(new String(Arrays.copyOfRange(data, start, scan)));
          start = scan + 1;
        }
        scan++;
      }
      if (scan - start > 0) result.add(new String(Arrays.copyOfRange(data, start, scan)));        }
    return result;
  }

  public static void main(String[] args) throws IOException {
    System.out.println(getLinuxCmdline(Integer.MAX_VALUE));
  }
}

وتشغيل هذا بحجج "شريط فو" في الكسوف يعطي هذا بالنسبة لي:

[/usr/lib/jvm/java-8-oracle/bin/java, -Dfile.encoding=UTF-8, -classpath, /home/mab/workspace/test/bin, test.Test, foo, bar]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top