2009-10-01 10 views
23

Jestem całkowicie zagubiony na tym: System.getProperty("user.home") i System.getProperty("user.name") zwraca znak zapytania "?".Java: System.getProperty ("user.home") zwraca "?"

System-Specs: 
Kubuntu 9.04 
Gnome 2.2.61 
Java 1.5.0_16 

Moja testcase wygląda tak:

$ more Test.java 
class Test { public static void main(String[] args) { System.out.println(System.getProperties()); } } 

Rezultatem jest (Dodano łamanie wierszy dla lepszej czytelności, otrzymuje nazwę firmy i własne nazwisko):

$ javac Test.java 
$ java Test 
{ 
java.runtime.name=Java(TM) 2 Runtime Environment, Standard Edition, 
sun.boot.library.path=/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre/lib/i386, 
java.vm.version=1.5.0_16-b02, 
java.vm.vendor=Sun Microsystems Inc., 
java.vendor.url=http://java.sun.com/, 
path.separator=:, 
java.vm.name=Java HotSpot(TM) Server VM, 
file.encoding.pkg=sun.io, 
sun.java.launcher=SUN_STANDARD, 
user.country=US, 
sun.os.patch.level=unknown, 
java.vm.specification.name=Java Virtual Machine Specification, 
user.dir=/home/MYCOMPANY/myname/temp, 
java.runtime.version=1.5.0_16-b02, 
java.awt.graphicsenv=sun.awt.X11GraphicsEnvironment, 
java.endorsed.dirs=/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre/lib/endorsed, 
os.arch=i386, 
java.io.tmpdir=/tmp, 
line.separator= 
, 
java.vm.specification.vendor=Sun Microsystems Inc., 
os.name=Linux, 
sun.jnu.encoding=UTF-8, 
java.library.path=/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre/lib/i386/server:/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre/lib/i386:/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre/../lib/i386, 
java.specification.name=Java Platform API Specification, 
java.class.version=49.0, 
sun.management.compiler=HotSpot Server Compiler, 
os.version=2.6.28-15-generic, 
user.home=?, 
user.timezone=, 
java.awt.printerjob=sun.print.PSPrinterJob, 
file.encoding=UTF-8, 
java.specification.version=1.5, 
java.class.path=., 
user.name=?, 
java.vm.specification.version=1.0, 
java.home=/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre, 
sun.arch.data.model=32, 
user.language=en, 
java.specification.vendor=Sun Microsystems Inc., 
java.vm.info=mixed mode, 
java.version=1.5.0_16, 
java.ext.dirs=/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre/lib/ext, 
sun.boot.class.path=/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre/lib/rt.jar:/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre/lib/i18n.jar:/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre/lib/sunrsasign.jar:/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre/lib/jsse.jar:/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre/lib/jce.jar:/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre/lib/charsets.jar:/home/MYCOMPANY/myname/apps/jdk1.5.0_16/jre/classes, 
java.vendor=Sun Microsystems Inc., 
file.separator=/, 
java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport.cgi, 
sun.io.unicode.encoding=UnicodeLittle, 
sun.cpu.endian=little, 
sun.desktop=gnome, 
sun.cpu.isalist= 
} 

Czy ktoś kiedykolwiek doświadczyć tego? Gdzie jest Java szukająca użytkownika i katalogu domowego? Sprawdziłem już zmienną środowiskową HOME, która jest ustawiona poprawnie.

+0

Hmmm. Nigdy tego nie widziałem. Czy 'echo $ HOME' działa z wiersza poleceń? Spróbuj wydrukować 'System.getProperties()'? –

+0

Od/etc/passwd maybe? Czy katalog domowy jest dynamiczny? – wds

+0

Czy jesteś pewien, że jest to implementacja słońca? – zedoo

Odpowiedz

27

To trochę krępujące, ale rozwiązaniem było po prostu użycie 64-bitowego JDK w 64-bitowym systemie. Skopiowałem wszystko z mojej starej maszyny, co oznaczało także 32-bitowy JDK i to był problem. To działało zgodnie z oczekiwaniami w 64-bitowym środowisku wykonawczym.

Przepraszamy za kłopot.

+14

Nie przepraszaj za kłopot. Jest to prawdziwy błąd w jvm, a ten post pomógł także innym osobom na SO. – extraneon

+3

To jest http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6972329 (niezatwierdzony jako błąd JDK, może to być problem systemowy). –

+0

Przez długi czas mieliśmy ten sam problem. Po przeczytaniu raportu o błędzie, którego dotyczył @PascalThivent, był to dokładnie nasz przypadek. Ten problem nie występuje na kontach lokalnych, ale dzieje się tak tylko na kontach LDAP. Problem polegał na tym, że 32-bitowa wersja biblioteki libnss_ldap nie została zainstalowana w naszym systemie. Po zainstalowaniu 32-bitowego pakietu nss_pam_ldap wszystko działało sprawnie. – akifusenet

1

To naprawdę interesujące. Wygląda na to, że właściwość user.home nie jest pobierana ze zmiennej środowiskowej $ HOME. Próbowałem to:

$ echo $HOME && java Test && unset HOME && echo $HOME && java Test 
/home/grzole 
/home/grzole 

/home/grzole 

Zauważ, że powłoka zapomina wartość zmiennej do domu, ale nie Java.

EDYCJA: Podejrzewam, że Java po prostu pobiera prefiks /home/ i dodaje nazwę użytkownika. Rozważ to:

# adduser b 
... 
# rm -fr /home/b 
# su - b 
No directory, logging in with HOME=/ 
$ cd /tmp/jb 
$ java Test 
/home/b 

Może nie masz katalogu /home w systemie plików w ogóle?

+0

Po prostu notatka dla każdego, kto się na to natknie, Java robi coś bardziej wyrafinowanego niż dołączanie nazwy użytkownika do "/ home /". Katalogi domowe na moich maszynach sieciowych z Linuksem znajdują się w "/ nethome" –

+0

... i jak sądzę - Java zgłasza, że ​​'/ nethome/b' jest odpowiednim katalogiem domowym? –

+0

Nie mam odpowiednich uprawnień do wykonania wszystkich operacji w drugim bloku na serwerach naszego projektu, ale musiałbym to założyć, biorąc pod uwagę, że wpis w bazie danych błędu Java (w połączeniu z innymi odpowiedziami/komentarzami) wskazuje, że Java może spaść z powrotem do LDAP, w zależności od konfiguracji systemu. –

6

Obejście, a nie rozwiązanie. Powinieneś być w stanie ustawić to przez dodanie argumentu -Duser.home=$HOME.

java -Duser.home=$HOME Test 
+0

Tak, poszedłem również w ten sposób, zmieniając nazwę oryginalnego java na java_bin i tworząc skrypt powłoki, który dodaje te właściwości do linii komend java_bin. Nie chcę tego jednak akceptować jako rozwiązania, ponieważ musi istnieć lepszy sposób. – digitalbreed

+0

Co zawiera rejestr strace? strace -o foobar.log java Test –

3

Co z innymi gwarantowanymi właściwościami? Co się stanie, jeśli zadzwonisz do czegoś podobnego?


    public static void printAllGuaranteedProperties() { 
     printAProperty ("java.version", "Java version number"); 
     printAProperty ("java.vendor", "Java vendor specific string"); 
     printAProperty ("java.vendor.url", "Java vendor URL"); 
     printAProperty ("java.home", "Java installation directory"); 
     printAProperty ("java.class.version", "Java class version number"); 
     printAProperty ("java.class.path", "Java classpath"); 
     printAProperty ("os.name", "Operating System Name"); 
     printAProperty ("os.arch", "Operating System Architecture"); 
     printAProperty ("os.version", "Operating System Version"); 
     printAProperty ("file.separator", "File separator"); 
     printAProperty ("path.separator", "Path separator"); 
     printAProperty ("line.separator", "Line separator"); 
     printAProperty ("user.name", "User account name"); 
     printAProperty ("user.home", "User home directory"); 
     printAProperty ("user.dir", "User's current working directory"); 
    } 
    public static void printAProperty (String propName, String desc) { 
     System.out.println ("Value for '" + desc + "' is '" + System.getProperty(propName) + "'."); 
    } 

2

wds ma rację w swoim komentarzu. Wartość user.home wydaje się być pobrana z/etc/passwd. Jaka jest Twoja linia w /etc/passwd dla Twojego użytkownika?

Jeśli zmieniłem wpis na /home/nonexisting, klasa Test wydrukowała /home/nonexisting. Czy zdarzyło Ci się mieć ? w/etc/passwd?

+1

Mój użytkownik nie jest w/etc/passwd. To samo dotyczy mojego kolegi ze swojej maszyny, ale działa tam. – digitalbreed

+0

@digitalbreed próbowałeś go tam dodać? –

+0

@AngeloNeuschitzer ten wątek ma 2,5 roku i nie pracuję już dla firmy, w której miałem ten problem, ale nie, nie zrobiłem tego, ponieważ nie miałem uprawnień root dla systemu. Zauważ, że istnieje również 2,5-letnie rozwiązanie tego problemu;) – digitalbreed

1

Potrzeba przepuszczenia kodu natywnego, aby dowiedzieć się, co dokładnie się dzieje. Zmienna user.home jest ustawiana przez moduły "PAM" w systemach Linux i jeśli moduł w użyciu generuje je dynamicznie, a implementacja Java próbuje uzyskać wartość bez jawnego używania PAM, zachowanie jest nieprzewidywalne, stąd "?"

1

Dla kompletności wygląda również, jeśli dany system jest skonfigurowany do używania uwierzytelniania LDAP (a nie/etc/passwd), wtedy problem opisany w tym raporcie błędu może być problemem: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6972329.Upewnij się, że odpowiedni plik libnss_ldap.so jest zainstalowany dla twojego systemu (np .: 32-bitowa biblioteka LDAP do użycia z 32-bitową Javą). Niektóre komendy, które mogą być pomocne w określeniu tego, mogą być następujące:

> rpm -qa | grep ldap 
nss-pam-ldapd-0.7.5-14.el6_2.1.x86_64 # Note x86_64 bit version installed 

> ls -l /lib64/libnss_ldap* 
-rwxr-xr-x. 1 root root 44328 Jan 3 2012 /lib64/libnss_ldap.so.2 
# ^^^ note 64 bit version installed. 

> ls /lib/libnss_ldap* 
ls: cannot access /lib/libnss_ldap*: No such file or directory 
# ^^^ Indicates 32 bit version is not installed! 
+0

Rekwizyty @PascalThivent kto podał link wcześniej, który zwrócił mi na tę możliwość. –

+0

To powinno być bardziej ogólne. Sprawdź '/ etc/nsswitch.conf' i uzyskaj pełną listę dostawców używanych do usługi' passwd'. Następnie upewnij się, że wszystkie odpowiednie biblioteki '/ lib/libnss_xxx' są zainstalowane również dla wersji 32-bitowej. Wpadłem na ten sam problem z dostawcą 'sss'. Czasami może być trudno znaleźć odpowiedni pakiet. –

0

Miałem ten sam problem. Jak wspomniano powyżej, problem polega na tym, że 32-bitowa Java potrzebuje również 32-bitowych bibliotek Ldap do zainstalowania. Jeśli nie, pojawia się opisany błąd.

Zainstalowanie libnss_ldap.so.2 i pakietów zależnych rozwiązuje problem.

Powiązane problemy