Java 防止使用静态修改器

Java 防止使用静态修改器,java,Java,我正在制作一个游戏,玩家必须编写自己的类来控制屏幕上的单位。但是,我想阻止他们在玩家类中使用静态变量,这样他们的单位就必须通过我开发的通信系统(即传输1s和0s)来传输信息,而不仅仅是访问静态“unitsTargeted”变量或其他任何变量。我可以阻止他们使用静态修改器吗?这要看情况而定。如果您无法控制源代码或运行环境,则无法阻止他们编译所需内容,也无法阻止他们执行所需内容 如果您可以控制构建(即:源代码被发送到您控制的系统,并且您可以控制编译),那么您可以构建自定义编译器 如果以某种方式控制运

我正在制作一个游戏,玩家必须编写自己的类来控制屏幕上的单位。但是,我想阻止他们在玩家类中使用静态变量,这样他们的单位就必须通过我开发的通信系统(即传输1s和0s)来传输信息,而不仅仅是访问静态“unitsTargeted”变量或其他任何变量。我可以阻止他们使用静态修改器吗?

这要看情况而定。如果您无法控制源代码或运行环境,则无法阻止他们编译所需内容,也无法阻止他们执行所需内容

如果您可以控制构建(即:源代码被发送到您控制的系统,并且您可以控制编译),那么您可以构建自定义编译器

如果以某种方式控制运行环境,则可以检查提供的类以查看其包含的内容。您可以使用一些字节码工具,或者更好的方法是使用反射API并检查是否有任何成员是静态的。使用反射获取成员列表后,对它们进行迭代并检查它们的
isStatic
。如果该类包含任何静态成员,则可以拒绝它

在您的例子中,由于您要从客户端将类上载到服务器,所以只需使用Java的反射API即可进行检查。如果客户机正在提交源代码,那么您将需要首先编译它,尽管我假设您在使用它之前已经这样做了

下面是我刚刚运行的一个测试用例:

package test.tmp;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

public class StaticChecker
{
    public static void main(String[] args)
    {
        for(Class c : new Class[]{StaticChecker.class, ClassWithStatics.class, ClassWithoutStatics.class})
        {
            System.out.println("For " + c + "...");

            boolean hasStatic = hasStaticMembers(c);
            System.out.println("\tIt contains static members: " + hasStatic);

            if(hasStatic)
            {
                System.out.println("\tThe static members are:");
                for(String s : checkStaticMembers(c))
                    System.out.println("\t\t" + s);
            }
        }
    }

    public static boolean hasStaticMembers(Class c)
    {
        return checkStaticMembers(c).size() > 0;
    }

    public static List<String> checkStaticMembers(Class c)
    {
        List<String> staticMemberNames = new ArrayList<String>();

        for(Field field : c.getDeclaredFields())
            if(Modifier.isStatic(field.getModifiers()))
                staticMemberNames.add(field.toString());

        for(Method method : c.getDeclaredMethods())
            if(Modifier.isStatic(method.getModifiers()))
                staticMemberNames.add(method.toString());

        return staticMemberNames;
    }
}

class ClassWithStatics
{
    public static int N = 3;
    private static String S = "?";

    private int n;

    void f() { System.out.println("f()"); }
    static void g() { System.out.println("g()"); }
    public static void h() { System.out.println("h()"); }
}

class ClassWithoutStatics
{
    int a;
    String b;
    void f() { System.out.println("f()"); }
}

请注意,您正在做的事情可能很危险,您应该非常小心地限制服务器端执行的代码可以做的事情。要毁了你的一天,所有人需要做的就是提交一个类,该类删除文件或安装不需要的文件或任何其他恶意操作。

不要在程序中使用静态变量,或者如果确实需要静态变量,则将其设为ThreadLocal,并将其保留在用户类无法访问的线程上

如果您希望您的程序相对安全,您还应该构建某种类型的类验证器,以确保这些类只使用允许的类,一个非常简短的允许类白名单


您可以使用ASM来创建这样的验证器。

不太可能,除非您想编写自己的编译器。将行为部分卸载到一个抽象类或接口中,玩家必须实现该类或接口。防止他们接触Players类。不清楚为什么
静态变量在Players类中无效。如果他们创建一个非静态的
unitsTargeted
变量,那也不坏吗?这听起来像是我需要做的。你能告诉我一些关于如何实际实施的好资源吗?我的计划是让玩家通过网页上传他们的课程到我控制的服务器上,我的源代码将在那里运行游戏并返回结果。所以理论上我应该能够在运行源代码之前检查玩家是否使用了任何静态变量。谢谢谢谢,这听起来像是我需要做的事情。我去查一下。
For class test.tmp.StaticChecker...
    It contains static members: true
    The static members are:
        public static void test.tmp.StaticChecker.main(java.lang.String[])
        public static java.util.List test.tmp.StaticChecker.checkStaticMembers(java.lang.Class)
        public static boolean test.tmp.StaticChecker.hasStaticMembers(java.lang.Class)
For class test.tmp.ClassWithStatics...
    It contains static members: true
    The static members are:
        public static int test.tmp.ClassWithStatics.N
        private static java.lang.String test.tmp.ClassWithStatics.S
        static void test.tmp.ClassWithStatics.g()
        public static void test.tmp.ClassWithStatics.h()
For class test.tmp.ClassWithoutStatics...
    It contains static members: false