防止使用静态修饰符

时间:2017-03-09 22:58:47

标签: java

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

2 个答案:

答案 0 :(得分:0)

这取决于。如果您无法控制源代码或运行环境,那么您无法阻止它们编译他们想要的内容,也不能阻止他们执行该操作。

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

如果以某种方式控制运行环境,则可以检查提供的类以查看它包含的内容。您可以使用一些字节码工具,或者更好,只需使用反射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()"); }
}

当我运行上述测试时,我得到以下输出:

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

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

答案 1 :(得分:0)

不要在程序中使用静态变量,或者如果你真的需要静态变量,请将其设置为ThreadLocal并将其保存在无法从用户类访问的线程上。

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

您可以使用ASM制作此类验证程序。