JVM 버전을 감지하는 Java 코드 작성


17

목적은 한 버전에서는 작동하고 다른 버전에서는 작동하는 호환성 변경, 부작용, 버그 및 / 또는 정의되지 않은 동작에 의존하는 JVM 버전을 감지하는 Java 코드를 작성하는 것입니다. 또한 공백과 읽기 쉬운 변수 이름을 희생하지 않고도 코드를 읽을 수 있어야합니다.

이러한 목표를 보장하기 위해 정확한 공식 규칙은 다음과 같습니다.

  1. 코드는 java로 작성해야하며 실행중인 JRE 버전을 출력해야합니다.

  2. 코드는 Java 버전을 감지하기 위해 특별히 제공되거나 JDK 또는 JRE 버전을 무료로 제공하는 JDK 또는 JRE API를 사용해서는 안됩니다.

  3. 코드는 리플렉션을 사용해서는 안됩니다.

  4. 이 코드는 핫스팟 Java SE 5, 6 및 7에서만 작동하지만 다른 JVM에서는 작동 할 수 있습니다.

  5. 코드는 클래스 경로에서 타사 라이브러리를 사용해서는 안됩니다.

  6. 코드는 다른 프로세스를 시작해서는 안됩니다 (java).

  7. 코드는 환경 변수를 사용해서는 안됩니다.

  8. 코드는 기존 파일이나 폴더를 찾기 위해 파일 시스템을 검색해서는 안됩니다.

  9. 코드는 하나의 파일에 포함되어야하며,를 통해 호출 할 수 public static void main(String[] args)또는 public static void main(String... args).

  10. 코드는 JRE에 존재하는 비공개 API를 사용해서는 안됩니다.

  11. 코드는 실행 중에 NoClassDefFoundError, NoSuchMethodError, ClassNotFoundException 또는 NoSuchMethodException을 생성하지 않아야합니다.

  12. 코드는 인터넷 또는 로컬 네트워크와 연결이 끊어진 시스템에서 실행해야합니다.

  13. 버전에서 다른 방식으로 작동하는 이유에 대한 설명을 제공해야합니다.

채점

최상의 솔루션을 측정하는 데 사용되는 방법은 max (n / s)입니다. 여기서 n은 이러한 규칙 (최소한 버전 5, 6 및 7)을 위반하지 않고 감지 된 여러 Java 버전 수이고 s는 어휘 토큰 수입니다. 솔루션에서.


더 나은 태그를 찾을 수 없어서 마지막 두 개를 제공해야했습니다. 또한 새 태그를 만들 충분한 담당자가 없습니다. 자바의 이유는 아마도 이식성이 뛰어난 언어이기 때문에 글쓰기가 매우 흥미로울 것이기 때문입니다. 또한 Java 버전은 오렌지와 사과를 비교할 필요없이 환경을 감지하는 항목을 균일하게 비교할 수있는 방식으로 정의됩니다.
Victor Stafusa

VM 버전 탐지가 시스템을 공격하는 단계라고 주장하는 [언제나] 고려할 수 있습니다. 다른 제안이 있다고 말할 수 없습니다.
dmckee

@dmckee [code-golf] 태그를 삭제했습니다. [underhanded] 태그를 추가하십시오. [java] 태그를 작성해 주시겠습니까?
Victor Stafusa

4
나는이 문제를 주제로 다루지 않기로 결심했다. 왜냐하면이 사이트에서 미숙 한 도전은 더 이상 주제가 아니기 때문이다. meta.codegolf.stackexchange.com/a/8326/20469
cat

@cat, 그 질문에 맞지 않기 때문에 대신 태그를 제거해야합니다.
피터 테일러

답변:


9

6/102 = 0.0588

6 가지 버전을 감지합니다. (I 삭제 한 후, 103에서 아래로 (102) 어휘 토큰을 가지고 public있는 public class).

import java.security.Signature;

class GuessVersion {
        public static void main(String[] args) {
                String version = "Java 1.1";
                try {
                        "".getBytes("ISO8859_13");
                        version = "Java 1.3";

                        "".getBytes("ISO8859_15");
                        version = "Java 1.4";

                        Signature.getInstance("SHA256withRSA");
                        version = "Java 5";

                        "".getBytes("KOI8_U");
                        version = "Java 6";

                        Signature.getInstance("SHA256withECDSA");
                        version = "Java 7";
                } catch(Exception e) {}
                System.out.println(version);
        }
}

Java 1.1 은 문자 인코딩 및 암호화 알고리즘을 Java에 도입했습니다. 이후 버전에서는 더 많은 인코딩 및 알고리즘이 추가되었습니다. 이 프로그램은 예외를 포착 할 때까지 인코딩 및 알고리즘을 사용하려고합니다. 누락 된 인코딩이 발생 java.io.UnsupportedEncodingException하고 누락 된 알고리즘이 발생합니다 java.security.NoSuchAlgorithmException.

Java의 4 가지 이전 버전이 포함 된 이전 PowerPC Macintosh가있었습니다. 내 OpenBSD 컴퓨터에는 두 가지 버전이 더 있으므로 다음 6 가지 버전을 테스트했습니다.

  • Mac OS 9.2.2 용 MRJ 2.2.6의 Java 1.1.8
  • Mac OS X Panther 용 Java 1.3.1_16
  • Mac OS X Tiger 용 Java 1.4.2_21
  • Mac OS X Tiger 용 Java 1.5.0_19
  • OpenBSD 5.5 용 OpenJDK 1.6.0_32
  • OpenBSD 5.5 용 OpenJDK 1.7.0_21

이 프로그램은 또한 OpenBSD 용 JamVM 1.5.4와 gcj 4.8.2에서 실행될 수 있지만 그것들을 다른 구현으로 식별하지는 않습니다. "Java 5"만 인쇄합니다.

Java 용 Mac OS 런타임

"한 번 쓰기, 어디에서나 실행!"덕분에이 프로그램을 한 번 작성하고 한 번 컴파일 한 다음 8 개의 가상 머신에서 GuessVersion.class를 하나씩 실행할 수 있습니다. 내 컬렉션에서 가장 오래된 버전 인 Java 1.1 용 컴파일러가 필요합니다.

내 컴파일러는 javacMRJ SDK 2.2 의 도구입니다. Classic Mac OS에는 명령 행이 없었기 때문에 javac파일과 옵션을 선택하고 "Do Javac"를 클릭하는 멋진 그래픽 도구입니다. 코드를 편집 한 후 "Do Javac"을 다시 클릭하면됩니다.

Classic Mac OS 용 MRJ SDK 2.2의 javac

GuessVersion.class를 실행하는 가장 쉬운 방법은 MRJ SDK 2.2의 또 다른 도구 인 JBindery에서 여는 것입니다. 런타임은 MRJ 2.2.6이며 Java 1.1.8의 구현입니다.


22

내 점수가 무엇인지 잘 모르겠습니다. 어떻게 어휘 토큰으로 간주되는지에 달려 있기 때문에 가능한 한 긴 문자열로 계산 시스템을 남용하려고합니다 ...

또한 7 가지 버전 또는 16 가지를 식별하는 것으로 계산하는지 여부에 달려 있습니다 (사소하게 최대 190까지 확장 할 수 있음).

class V extends ClassLoader
{
    public static void main(String[]args)
    {
        for(byte b=60;;)
            try {
                byte[]buf="\u00ca\u00fe\u00ba\u00be\u0000\u0000\u00002\u0000\u0005\u0007\u0000\u0003\u0007\u0000\u0004\u0001\u0000\u0001A\u0001\u0000\u0010java/lang/Object\u0006\u0000\u0000\u0001\u0000\u0002\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000".getBytes("ISO-8859-1");
                buf[7]=b--;
                new V().defineClass(buf,0,53);
                System.out.println(b-43);
                break;
            }
            catch(Throwable t){}
    }
}

클래스 형식의 주요 버전 번호가 내림차순으로 사용자 정의 클래스 로더에서 인터페이스를 정의하려고 시도합니다. 를 던지지 않는 첫 번째 java.lang.UnsupportedClassVersionError것은 VM의 버전에 해당합니다.


84 개의 토큰을 계산했습니다. 그래도 아직 테스트하지 않았습니다.
Victor Stafusa

당신의 대답은 온화합니다. 를 사용하여 83 개의 토큰으로 간단하게 줄일 수 String... args있습니다.
Victor Stafusa

@Victor, 그것은 7 가지 버전을 더 지원하는지에 대한 질문을 복잡하게 할 것입니다. Java 5 구문을 지원하고 Java 1 호환 클래스 파일로 컴파일하는 컴파일러는 없습니다.
피터 테일러

좋은 지적. 나는 그것을 잊었다.
Victor Stafusa

1
17 개의 토큰을 추가 할 때까지 Java 1.1.8 (MRJ 2.2.6)에서이를 컴파일하지 못했습니다 protected Class loadClass(String name, boolean resolve) { return Object.class; }. 현재 API 문서는 이것이 Java 1.2 이전의 추상적 인 방법이었던 것을 언급하지 않습니다. 메소드가 "java.lang.Object"에 대한 하나의 호출을 가져 오기 때문에 Object.class를 리턴합니다.
kernigh

8
class Evil {
    public static void main(String... args) {
        String s1 = "Good";
        s1 += "morning";
        int a = 7;
        if (s1 != s1.intern())
            try {
                a--;
                javax.xml.datatype.DatatypeFactory.newInstance().newXMLGregorianCalendar().equals(null);
            } catch (Throwable e) {
                a--;
            }
        System.out.println(a);
    }
}

interning 알고리즘은 Java 6과 7 사이에서 변경되었습니다. /programming//a/7224864/540552 참조

XMLGregorianCalendar.equals (null)은 Java 5에서 NullPointerException을 발생시키는 데 사용되었지만 이는 Java 6에서 수정되었습니다. http://bugs.sun.com/view_bug.do?bug_id=6285370

100 96 92 87 85 토큰은 여기에 있습니다. 토큰을 7 개 줄인 Peter Taylor에게 감사합니다.


1
버전 번호를 s1에 저장하여 3 개의 토큰을 저장할 수 있습니다. DatatypeConfigurationException던지지 않을 것이라는 가정하에 Throwable을 직접 잡아서 더 2를 절약 할 수 있습니다 .
피터 테일러

1
또는 더 좋게 유지 int a하면서 즉시 초기화하면 if블록이 비워집니다. 조건을 무효화하고 다른 것을 제거하고 --에 직접 할당 하는 대신 사용하십시오 a.
피터 테일러
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.