首页 > 解决方案 > 有没有办法软更改 Java 版本?

问题描述

我有一个旧应用程序拒绝在未经测试的 Java 版本上启动。不幸的是,它是一个废弃软件,因此几乎没有机会对其进行更新。它抱怨JVM是由Oracle而不是Sun制造的。

在 MS DOS 的日子里,有一个setver命令允许设置应用程序看到的操作系统版本,有没有类似于 JVM 上的东西?

标签: jvm

解决方案


我将使用 OpenJDK 项目中的asmtools将文件反汇编为字节码汇编格式。例如,一个 helloworld 看起来像这样 ( jdis NameOfClass.class>NameOfClass.j):

super public class A
    version 59:0
{

public Method "<init>":"()V"
    stack 1 locals 1
{
        aload_0;
        invokespecial   Method java/lang/Object."<init>":"()V";
        return;
}

public static Method main:"([Ljava/lang/String;)V"
    stack 2 locals 1
{
        getstatic   Field java/lang/System.out:"Ljava/io/PrintStream;";
        ldc String "Hello World!";
        invokevirtual   Method java/io/PrintStream.println:"(Ljava/lang/String;)V";
        return;
}

} // end Class A

之后,您编辑文件:

super public class A
    version 59:0
{

public Method "<init>":"()V"
    stack 1 locals 1
{
        aload_0;
        invokespecial   Method java/lang/Object."<init>":"()V";
        return;
}

public static Method main:"([Ljava/lang/String;)V"
    stack 2 locals 1
{
        getstatic   Field java/lang/System.out:"Ljava/io/PrintStream;";
        ldc String "Hello Stackoverflow!";
        invokevirtual   Method java/io/PrintStream.println:"(Ljava/lang/String;)V";
        return;
}

} // end Class A

然后您可以再次将其编译为 .class :

jasm NameOfClass.j

然后就可以用Java正常运行了。

这只是一个例子。

您只需要使用检查版本的方法找到类。例如,您可以解压缩 jar 文件,如果不匹配版本的消息是,例如:

“检测到错误版本:”

你可以只用 grep (grep -R Bad.version)然后你就可以上课了。在那里,您将不得不更改负责检查 Java 版本的方法。

一个例子:

A.java:

public class A{
        static boolean hasMatchingJavaVersion() {
                return System.getProperty("java.version").matches("1.4.*");//Just Java 1.4
        }
        public static void main(String[] args) {
                if(hasMatchingJavaVersion()) {
                  System.out.println("Matches");
                } else {
                  System.out.println("Bad version");
                  System.exit(-1);
                }
        }
}

运行它:(false在 Java 15 上,例如)

作为组装。


super public class A
    version 59:0
{

public Method "<init>":"()V"
    stack 1 locals 1
{
        aload_0;
        invokespecial   Method java/lang/Object."<init>":"()V";
        return;
}

static Method hasMatchingJavaVersion:"()Z"
    stack 2 locals 0
{
        ldc String "java.version";
        invokestatic    Method java/lang/System.getProperty:"(Ljava/lang/String;)Ljava/lang/String;";
        ldc String "1.4.*";
        invokevirtual   Method java/lang/String.matches:"(Ljava/lang/String;)Z";
        ireturn;
}

public static Method main:"([Ljava/lang/String;)V"
    stack 2 locals 1
{
        invokestatic    Method hasMatchingJavaVersion:"()Z";
        ifeq    L17;
        getstatic   Field java/lang/System.out:"Ljava/io/PrintStream;";
        ldc String "Matches";
        invokevirtual   Method java/io/PrintStream.println:"(Ljava/lang/String;)V";
        goto    L29;
    L17:    stack_frame_type same;
        getstatic   Field java/lang/System.out:"Ljava/io/PrintStream;";
        ldc String "Bad version";
        invokevirtual   Method java/io/PrintStream.println:"(Ljava/lang/String;)V";
        iconst_m1;
        invokestatic    Method java/lang/System.exit:"(I)V";
    L29:    stack_frame_type same;
        return;
}

} // end Class A

此方法检查版本:

static Method hasMatchingJavaVersion:"()Z"
    stack 2 locals 0
{
        ldc String "java.version";
        invokestatic    Method java/lang/System.getProperty:"(Ljava/lang/String;)Ljava/lang/String;";
        ldc String "1.4.*";
        invokevirtual   Method java/lang/String.matches:"(Ljava/lang/String;)Z";
        ireturn;
}

因此,您可以例如将其更改为:

static Method hasMatchingJavaVersion:"()Z"
    stack 2 locals 0
{
        iconst_1;//Load true, always return true
        ireturn;
}

然后用jasm.

编辑:

JVM 是由 Oracle 而不是 Sun 制造的。

我过度阅读了这个,但它的工作方式与上述相同,只是另一个系统属性和一些其他小的变化,


推荐阅读