Tujuannya adalah untuk menulis kode java yang mendeteksi versi JVM dengan mengandalkan perubahan kompatibilitas, efek samping, bug dan / atau perilaku tidak terdefinisi yang bekerja dengan cara dalam satu versi dan cara lain di versi lain. Selanjutnya, kode harus setidaknya sedikit terbaca, tanpa mengorbankan spasi putih dan nama variabel yang dapat dibaca.
Untuk memastikan tujuan itu, aturan formal yang tepat adalah:
Kode harus ditulis dalam java dan harus menampilkan versi JRE di mana ia berjalan.
Kode tidak boleh menggunakan JDK atau JRE API yang disediakan khusus untuk mendeteksi versi java atau yang memberikan versi JDK atau JRE secara gratis.
Kode tidak boleh menggunakan refleksi.
Kode ini hanya diperlukan untuk bekerja di Hotspot Java SE 5, 6 dan 7, tetapi dapat bekerja di JVM lainnya.
Kode tidak boleh menggunakan perpustakaan pihak ketiga apa pun di classpath.
Kode tidak boleh memulai proses lain, java atau tidak.
Kode tidak boleh menggunakan variabel lingkungan.
Kode tidak boleh mencari sistem file untuk mencari file atau folder yang sudah ada.
Kode harus dimuat dalam satu file dan dipanggil melalui
public static void main(String[] args)
ataupublic static void main(String... args)
.Kode tidak boleh menggunakan API non-publik apa pun yang ada di JRE.
Kode tidak boleh menghasilkan NoClassDefFoundError, NoSuchMethodError, ClassNotFoundException atau NoSuchMethodException selama eksekusi.
Kode harus dijalankan dalam sistem yang terputus dari internet atau dari jaringan lokal apa pun.
Anda harus memberikan penjelasan mengapa berperilaku dalam satu cara dalam versi dan cara lain di versi lain.
Mencetak gol
Metode yang digunakan untuk mengukur solusi terbaik adalah maks (n / s), di mana n adalah jumlah versi java yang berbeda yang terdeteksi tanpa melanggar salah satu aturan ini (setidaknya versi 5, 6 dan 7) dan s adalah jumlah token leksikal dalam solusinya.
sumber
Jawaban:
6/102 = 0,0588
Mendeteksi 6 versi. Memiliki 102 token leksikal (turun dari 103, setelah saya dihapus
public
dipublic class
).Java 1.1 memperkenalkan pengkodean karakter dan algoritma kriptografi ke Java. Versi selanjutnya menambahkan lebih banyak penyandian dan algoritma. Program ini mencoba menggunakan penyandian dan algoritme hingga ada pengecualian. Saya mengharapkan penyandian yang hilang untuk membuang
java.io.UnsupportedEncodingException
dan algoritma yang hilang untuk melemparjava.security.NoSuchAlgorithmException
.Saya memiliki PowerPC Macintosh lama dengan empat versi lama Java. Mesin OpenBSD saya memiliki dua versi lagi, jadi saya menguji enam versi ini:
Program ini juga dapat berjalan di JamVM 1.5.4 dan gcj 4.8.2 untuk OpenBSD, tetapi tidak mengidentifikasi mereka sebagai implementasi yang berbeda. Ini hanya mencetak "Java 5".
Runtime Mac OS untuk Java
Berkat "Tulis sekali, jalankan di mana-mana!", Saya dapat menulis program ini sekali, kompilasi sekali, dan jalankan satu GuessVersion.class di semua delapan mesin virtual. Saya memerlukan kompiler untuk Java 1.1, versi tertua dalam koleksi saya.
Kompiler saya adalah
javac
alat dari MRJ SDK 2.2. Karena Classic Mac OS tidak memiliki baris perintah,javac
adalah alat yang cukup grafis di mana saya memilih file dan opsi dan klik "Do Javac". Setelah saya mengedit kode saya, saya cukup klik "Do Javac" lagi.Cara termudah untuk menjalankan GuessVersion.class adalah membukanya di JBindery, alat lain dari MRJ SDK 2.2. Runtime adalah MRJ 2.2.6, sebuah implementasi dari Java 1.1.8.
sumber
Saya tidak yakin berapa skor saya, karena itu tergantung pada apa yang Anda anggap sebagai token leksikal, tapi saya mencoba menyalahgunakan sistem penghitungan sebanyak mungkin dengan string panjang ...
Ini juga tergantung pada apakah Anda menghitung ini sebagai mengidentifikasi 7 versi yang berbeda atau 16 ... (Ini dapat dengan mudah diperpanjang hingga 190).
Ini bekerja dengan mencoba untuk mendefinisikan antarmuka dalam classloader kustom dengan turun nomor versi utama dari format kelas. Yang pertama yang tidak melempar
java.lang.UnsupportedClassVersionError
korespondensi dengan versi VM.sumber
String... args
.protected Class loadClass(String name, boolean resolve) { return Object.class; }
. Dokumen API saat ini lalai menyebutkan bagaimana ini adalah metode abstrak sebelum Java 1.2. Saya mengembalikan Object.class karena metode ini mendapat satu panggilan untuk "java.lang.Object".Algoritma interning berubah antara Java 6 dan 7. Lihat /programming//a/7224864/540552
XMLGregorianCalendar.equals (null) digunakan untuk melempar NullPointerException di java 5, tapi ini diperbaiki di java 6. Lihat http://bugs.sun.com/view_bug.do?bug_id=6285370
10096928785 token di sini. Terima kasih kepada Peter Taylor karena mengurangi 7 token.sumber
DatatypeConfigurationException
tidak akan dibuang.int a
tetapi segera inisialisasi, sehinggaif
blok menjadi kosong. Negasikan kondisi tersebut, hapus yang lain, dan gunakan--
alih-alih penetapan langsung kea
.