JVM系统变量的妙用

JVM系统变量说明

在java应用中,JVM系统变量指的是通过System.getProperty("xxx") 能获取的变量。可以通过在jvm的启动参数中添加**-Dkey=value**来进行键值对的配置。其灵活性和高优先级特性可以使其成为解决复杂场景问题中的"瑞士军刀"。

JVM系统变量有如下的优势

  • 优先级最高,大于配置文件(如application.yml)
  • 即使生效,无需等待spring框架初始化就可以使用
  • 跨平台通用,jvm启动时注入,与操作系统无关

接下来看一下JVM参数使用

JVM系统变量使用

一个简单的springboot项目配置如下

XML 复制代码
server:
  port: 9091

mybatis:
  typeAliasesPackage: com.tml.mouseDemo.model
  mapperLocations: classpath:mapper/*.xml

spring:
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:db_users;MODE=MYSQL;INIT=RUNSCRIPT FROM 'classpath:sql/init.sql'
    username: tml
    password: helloTml
  h2:
    console:
      enabled: true

  logging:
    level:
      com.tml.mouseDemo.data.*: debug
    config: classpath:logback.xml


tml:
  name : helloWorld

一个简单的测试类

java 复制代码
package com.tml.mouseDemo.job;

import com.tml.mouseDemo.mapper.UserMapper;
import com.tml.mouseDemo.model.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class MyCoreJob {

    @Autowired
    private UserMapper userMapper;

    @Value("${tml.name:}")
    private String name;

    @Scheduled(cron = "0/10 * * * * ?")
    public void testOk(){
        log.info("testOk,name:{}", name);
        List<User> list = userMapper.listByName("tml");
        log.info("oneUser:{}", list.size());
    }
}

直接运行springboot主类,运行结果,如下

现在在启动参数中增加JVM系统变量,如下

运行结果如下

从这个简单的代码案例中,可以发现JVM系统变量的优先级确实是高于application.yml配置文件的,可以通过这个来覆盖配置文件中的变量。

生效时间块,这个是毫无疑问的,可以利用这个特点,在框架中去使用。比如在logback框架中就有读取JVM系统变量的值

需要注意的是,获取jvm系统变量可能会出现运行时异常SecurityException,为了保障系统的健壮,需要手动处理这个异常,避免将异常抛给调用方。

java 复制代码
    /**
     * Very similar to <code>System.getProperty</code> except that the
     * {@link SecurityException} is absorbed.
     *
     * @param key The key to search for.
     * @return the string value of the system property.
     */
    public static String getSystemProperty(String key) {
        try {
            return System.getProperty(key);
        } catch (SecurityException e) {
            return null;
        }
    }

JVM系统变量应用场景示例

利用灵活的配置属性调整代码逻辑

比如,在一个需要登录的web系统中,为了方便本地测试,可能会注释掉与权限相关的代码逻辑,这样做是没有问题的,但是不够好,可能会把注释的代码也提交上去了,这个时候,就可以使用System.getProperties("xxx")来进行优化代码,本地启动的时候添加对应的jvm参数,生产环境去掉这个jvm参数

这样做的好处就是,大家直接将代码clone下来,就能本地debug调试,而不需要本地做额外的一些代码修改,大大提升效率

比如这样

java 复制代码
public class AuthInterceptor implements HandlerInterceptor {
    
    // 定义系统属性的Key(避免硬编码字符串)
    private static final String AUTH_DISABLE_KEY = "auth.disable";
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 检查是否启用了权限绕过开关
        if (Boolean.parseBoolean(System.getProperty(AUTH_DISABLE_KEY, "false"))) {
            return true; // 本地测试跳过所有权限校验
        }
        
        // 正式环境的权限校验逻辑
        User user = (User) request.getAttribute("currentUser");
        if (!user.hasPermission("admin")) {
            throw new AuthException("无权限访问");
        }
        return true;
    }
}

本地的jvm启动

添加JVM参数临时禁用权限校验

java -Dauth.disable=true -jar app.jar

生产环境的jvm启动

不添加参数,权限校验正常生效

java -jar app.jar

元数据传递标识身份

为微服务实例添加唯一标识

java -Dapp.instance.id=$(uuidgen) -jar app.jar

注意:这里的uuidgen是一个linux bash命令,返回的是一个uuid的字符串

在日志和Metrics中携带实例ID,便于分布式追踪和监控

JVM系统变量注意事项

在使用jvm系统变量的时候,需要注意点如下

  1. 避免错误的覆盖,在配置jvm参数的时候,全局检索一下
  2. 注意System.getProperties()可能会抛出SecurityException带来的问题

那么,朋友们,你们在使用JVM系统变量来解决什么问题呢?欢迎评论区留言~

相关推荐
XMYX-07 分钟前
解决 Redis 后台持久化失败的问题:内存不足导致 fork 失败
java·数据库·redis
bigcarp26 分钟前
理解langchain langgraph 官方文档示例代码中的MemorySaver
java·前端·langchain
橘猫云计算机设计1 小时前
基于jspm校园安全管理系统(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·安全·毕业设计
幽络源小助理1 小时前
SpringBoot学生宿舍管理系统的设计与开发
java·spring boot·后端·学生宿舍管理
猿java1 小时前
源码分析:Spring IOC容器初始化过程
java·后端·spring
阿拉保1 小时前
C++复试笔记(四)
java·c++·笔记
蓝莓浆糊饼干2 小时前
请简述一下String、StringBuffer和“equals”与“==”、“hashCode”的区别和使用场景
android·java
好多大米2 小时前
3.JVM-内部结构
java·jvm·性能优化
小薛博客2 小时前
Git常用操作之GitLab
java·git·gitlab·github·idea
小梁不秃捏2 小时前
Java 代理模式:从静态代理到动态代理
java·开发语言·代理模式