分类 软件开发 下的文章

Go 的随机数生成器是生成难以猜测的密码的好方法。

你可以使用 Go 编程语言 提供的随机数生成器来生成由 ASCII 字符组成的难以猜测的密码。尽管本文中提供的代码很容易阅读,但是你仍需要了解 Go 的基础知识,才能更好地理解它。如果你是对 Go 还不熟悉,请阅读 Go 语言之旅 来了解更多信息,然后返回此处。

在介绍实用程序和它的代码之前,让我们先来看看这个 ASCII 表的子集,它可以在 man ascii 命令的输出中找到:

30 40 50 60 70 80 90 100 110 120
 ---------------------------------
0:    (  2  <  F  P  Z  d   n   x
1:    )  3  =  G  Q  [  e   o   y
2:    *  4  >  H  R  \  f   p   z
3: !  +  5  ?  I  S  ]  g   q   {
4: "  ,  6  @  J  T  ^  h   r   |
5: #  -  7  A  K  U  _  i   s   }
6: $  .  8  B  L  V  `  j   t   ~
7: %  /  9  C  M  W  a  k   u  DEL
8: &  0  :  D  N  X  b  l   v
9: '  1  ;  E  O  Y  c  m   w

在所有 ASCII 字符中,可打印字符的十进制值范围为 33 到 126,其他的 ASCII 值都不适合用于密码。因此,本文介绍的实用程序将生成该范围内的 ASCII 字符。

生成随机整数

第一个实用程序名为 random.go,它生成指定数量的随机整数,这些整数位于给定范围内。random.go 最重要的部分是这个函数:

func random(min, max int) int {
    return rand.Intn(max-min) + min
}

此函数使用了 rand.Intn() 函数来生成一个属于给定范围的随机整数。请注意,rand.Intn() 返回一个属于 [0,n) 的非负随机整数。如果它的参数是一个负数,这个函数将会抛出异常,异常消息是:panic: invalid argument to Intn。你可以在 math/rand 文档 中找到 math/rand 包的使用说明。

random.go 实用程序接受三个命令行参数:生成的整数的最小值、最大值和个数。

编译和执行 random.go 会产生这样的输出:

$ go build random.go
$ ./random
Usage: ./random MIX MAX TOTAL
$ ./random 1 3 10
2 2 1 2 2 1 1 2 2 1

如果你希望在 Go 中生成更安全的随机数,请使用 Go 库中的 crypto/rand 包。

生成随机密码

第二个实用程序 randomPass.go 用于生成随机密码。randomPass.go 使用 random() 函数来生成随机整数,它们随后被以下 Go 代码转换为 ASCII 字符:

for {
    myRand := random(MIN, MAX)
    newChar := string(startChar[0] + byte(myRand))
    fmt.Print(newChar)
    if i == LENGTH {
        break
    }
    i++
}

MIN 的值为 0MAX 的值为 94,而 startChar 的值为 !,它是 ASCII 表中第一个可打印的字符(十进制 ASCII 码为 33)。因此,所有生成的 ASCII 字符都位于 !~ 之间,后者的十进制 ASCII 码为 126

因此,生成的每个随机数都大于 MIN,小于 MAX,并转换为 ASCII 字符。该过程继续进行,直到生成的密码达到指定的长度。

randomPass.go 实用程序接受单个(可选)命令行参数,以定义生成密码的长度,默认值为 8,这是一个非常常见的密码长度。执行 randomPass.go 会得到类似下面的输出:

$ go run randomPass.go 1
Z
$ go run randomPass.go 10
#Cw^a#IwkT
$ go run randomPass.go
Using default values!
[PP8@'Ci

最后一个细节:不要忘记调用 rand.Seed(),并提供一个 种子 seed 值,以初始化随机数生成器。如果你始终使用相同的种子值,随机数生成器将生成相同的随机整数序列。

随机数生成代码

你可以在 GitHub 找到 random.gorandomPass.go 的源码。你也可以直接在 play.golang.org 上执行它们。

我希望这篇文章对你有所帮助。如有任何问题,请在下方发表评论或在 Twitter 上与我联系。


via: https://opensource.com/article/18/5/creating-random-secure-passwords-go

作者:Mihalis Tsoukalos 选题:lkxed 译者:lkxed 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

使用 TotalCross 来快速构建嵌入式系统程序的用户界面。

 title=

从头开始构建 GUI 是一个非常耗时的过程,以硬编码的方式处理所有的位置和对齐对于一些程序员来说确实很困难。所以在本文中,我将演示如何使用 XML 加快这一过程。

本项目使用 TotalCross 作为目标框架。TotalCross 是一个开源的跨平台软件开发工具包(SDK),旨在更快地为嵌入式设备创建 GUI。TotalCross 无需在设备上运行 Java 即可提供 Java 的开发优势,因为它使用自己的字节码和虚拟机( TC 字节码 TC bytecode 和 TCVM)来增强性能。

我还使用了 Knowcode-XML,这是一个用于 TotalCross 框架的开源 XML 解析器,它可以将 XML 文件转换为 TotalCross 组件。

项目需求

要重现此项目,你需要:

制作嵌入式应用程序

该应用程序由一个具有扫描、打印和复印等基本打印功能的嵌入式 GUI 组成。

 title=

构建这个 GUI 需要几个步骤,包括使用 Android-XML 生成 GUI,然后使用 Knowcode-XML 解析器在 TotalCross 框架上运行它。

1、生成 Android XML

要创建 XML 文件,首先构建一个简单的 Android 屏幕,然后对其进行自定义。如果你不知道如何编写 Android-XML,或者你只是想简单尝试一下,你可以从这个 GitHub 项目 中下载这个应用程序的 XML。该项目还包含渲染 GUI 要用到的图片。

2、调整 XML

生成 XML 文件后,你需要进行一些微调以确保所有内容都已经对齐、比例正确并且图像的路径正确。

将 XML 布局添加到 Layouts 文件夹,将所有资源添加到 Drawable 文件夹。然后你就可以开始自定义 XML 了。

例如,如果想要更改 XML 对象的背景,可以更改 android:background 属性:

android:background="@drawable/scan"

你也可以使用 tools:layout_editor_absoluteXtools:layout_editor_absoluteY 更改对象的位置:

tools:layout_editor_absoluteX="830dp"
tools:layout_editor_absoluteY="511dp"

或者使用 android:layout_widthandroid:layout_height 更改对象的大小:

android:layout_width="70dp"
android:layout_height="70dp"

如果要在对象上放置文本,可以使用 android:textSizeandroid:textandroid:textStyleandroid:textColor

android:textStyle="bold"
android:textColor="#000000"
android:textSize="20dp"
android:text="2:45PM"

下面是一个完整的 XML 对象的示例:

    <ImageButton
           android:id="@+id/ImageButton"
           android:layout_width="70dp"
           android:layout_height="70dp"
           tools:layout_editor_absoluteX="830dp"
           tools:layout_editor_absoluteY="511dp"
           android:background="@drawable/home_config" />

3、在 TotalCross 上运行 GUI

完成所有 XML 调整后,就可以在 TotalCross 上运行它了。在 TotalCross 扩展(LCTT 译注:在 VSCode 里面)上创建一个新项目,并将 XMLDrawable 文件夹添加到 Main 文件夹里。如果你仍然不确定如何创建 TotalCross 项目,请参阅我们的 入门指南

配置好环境后,使用 totalcross.knowcode.parse.XmlContainerFactoryimport totalcross.knowcode.parse.XmlContainerLayout 在 TotalCross 框架上使用 XML GUI。 你可以在其 GitHub 页面 上找到更多关于使用 KnowCode-XML 的信息。

4、添加过渡效果

这个项目的平滑过渡效果是由 SlidingNavigator 类创建的,它使用 TotalCross 的 ControlAnimation 类从一个屏幕滑到另一个屏幕。

XMLpresenter 类上调用 SlidingNavigator

new SlidingNavigator(this).present(HomePresenter.class);

SlidingNavigator 类上实现 present 函数:

public void present(Class<? extends XMLPresenter> presenterClass)
         throws InstantiationException, IllegalAccessException {
      final XMLPresenter presenter = cache.containsKey(presenterClass) ? cache.get(presenterClass)
            : presenterClass.newInstance();
      if (!cache.containsKey(presenterClass)) {
         cache.put(presenterClass, presenter);
      }

      if (presenters.isEmpty()) {
         window.add(presenter.content, LEFT, TOP, FILL, FILL);
      } else {
         XMLPresenter previous = presenters.lastElement();

         window.add(presenter.content, AFTER, TOP, SCREENSIZE, SCREENSIZE, previous.content);

使用动画控件中的 PathAnimation 来创建从一个屏幕到另一个屏幕的滑动动画:

         PathAnimation.create(previous.content, -Settings.screenWidth, 0, new ControlAnimation.AnimationFinished() {
            @Override
            public void onAnimationFinished(ControlAnimation anim) {
               window.remove(previous.content);
            }
         }, 1000).with(PathAnimation.create(presenter.content, 0, 0, new ControlAnimation.AnimationFinished() {
            @Override
            public void onAnimation Finished(Control Animation anim) {
               presenter.content.setRect(LEFT, TOP, FILL, FILL);
            }
         }, 1000)).start();
      }
      presenter.setNavigator(this);
      presenters.push(presenter);
      presenter.bind2();
      if (presenter.isFirstPresent) {
         presenter.onPresent();
         presenter.isFirstPresent = false;
      }

5、加载环形进度条

打印机应用程序的另一个不错的功能是显示进度的加载屏幕动画。它包括文本和旋转动画。

 title=

通过添加定时器和定时器监听器来更新进度标签,然后调用函数 spinner.start() 来实现此功能。所有的动画都是由 TotalCross 和 KnowCode 自动生成的:

public void startSpinner() {
        time = content.addTimer(500);
        content.addTimerListener((e) -> {
            try {
                progress(); // Updates the Label
            } catch (InstantiationException | IllegalAccessException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        });
        Spinner spinner = (Spinner) ((XmlContainerLayout) content).getControlByID("@+id/spinner");
        spinner.start();
    }

这里的环形进度条被实例化为对 XML 文件中描述的 XmlContainerLayout spinner 的引用:

<ProgressBar
android:id="@+id/spinner"
android:layout_width="362dp"
android:layout_height="358dp"
tools:layout_editor_absoluteX="296dp"
tools:layout_editor_absoluteY="198dp"
   android:indeterminateTint="#2B05C7"
style="?android:attr/progressBarStyle" />

6、构建应用程序

是时候构建应用程序了。你可以在 pom.xml 中查看和更改 目标系统 target systems 。 请确保 Linux Arm 目标可用。

如果你使用的是 VSCode,请按下键盘上的 F1 键,选择 TotalCross: Package 并等待完成。 然后就可以在 Target 文件夹中看到安装文件了。

7、在树莓派上部署和运行应用程序

要使用 SSH 协议在 树莓派 上部署应用程序,请按键盘上的 F1。选择 TotalCross: Deploy&Run 并提供有关你的 SSH 连接的信息,如:用户名、IP地址、密码和应用程序路径。

 title=

 title=

 title=

 title=

 title=

总结

KnowCode 让使用 Java 创建和管理应用程序屏幕变得更加容易。Knowcode-XML 将你的 XML 转换为 TotalCross GUI 界面,然后生成二进制文件以在你的树莓派上运行。

将 KnowCode 技术与 TotalCross 相结合,使你能够更快地创建嵌入式应用程序。 你可以访问我们在 GitHub 上的 嵌入式示例 并编辑你自己的应用程序,了解你还可以做什么。

如果你有问题、需要帮助,或者只是想与其他嵌入式 GUI 开发人员互动,请随时加入我们的 Telegram 小组,讨论任何框架上的嵌入式应用程序。


via: https://opensource.com/article/21/3/raspberry-pi-totalcross

作者:Edson Holanda Teixeira Junior 选题:lujun9972 译者:CoWave-Fall 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在当今快节奏的数字世界中,机构们使用低代码/无代码(LC/NC)应用来快速构建新的信息系统。本文将介绍 PyCaret,这是一个用 Python 编写的低代码机器学习库。

Featured-image-of-pycaret

PyCaret 是 R 编程语言中 Caret( 分类和回归训练 Classification And REgression Training 的缩写)包的 Python 版本,具有许多优点。

  • 提高工作效率: PyCaret 是一个低代码库,可让你提高工作效率。由于花费更少的时间进行编码,你和你的团队现在可以专注于业务问题。
  • 易于使用: 这个简单易用的机器学习库将帮助你以更少的代码行执行端到端的机器学习实验。
  • 可用于商业: PyCaret 是一个可用于商业的解决方案。它允许你从选择的 notebook 环境中快速有效地进行原型设计。

你可以在 Python 中创建一个虚拟环境并执行以下命令来安装 PyCaret 完整版:

pip install pycaret [full]

机器学习从业者可以使用 PyCaret 进行分类、回归、聚类、异常检测、自然语言处理、关联规则挖掘和时间序列分析。

使用 PyCaret 构建分类模型

本文通过从 PyCaret 的数据仓库中获取 Iris 数据集来解释使用 PyCaret 构建分类模型。

我们将使用 Google Colab 环境使事情变得简单,并按照下面提到的步骤进行操作。

步骤 1

首先,通过给出以下命令安装 PyCaret:

pip install pycaret

步骤 2

接下来,加载数据集,如图 2 所示:

Loading the data set

from pycaret.datasets import get_data
dataset = get_data('iris') 
(或者)
import pandas as pd 
dataset = pd.read_csv('/path_to_data/file.csv')

步骤 3

现在设置 PyCaret 环境,如图 2 所示:

PyCaret environment setup

from pycaret.classification import *
clf1 = setup(data=dataset, target = ‘species’)

PyCaret environment setup result

使用 PyCaret 构建任何类型的模型,环境设置是最重要的一步。默认情况下,setup() 函数接受参数 data(Pandas 数据帧)和 target(指向数据集中的类标签变量)。setup() 函数的结果如图 3 所示。 setup() 函数默认将 70% 的数据拆分为训练集,30% 作为测试集,并进行数据预处理,如图 3 所示。

步骤 4

接下来,找到最佳模型,如图 4 所示:

Finding the best model

best = compare_models()

默认情况下,compare_models() 应用十倍交叉验证,并针对具有较少训练时间的不同分类器计算不同的性能指标,如准确度、AUC、召回率、精度、F1 分数、Kappa 和 MCC,如图 4 所示。通过将 tubro=True 传递给 compare_models() 函数,我们可以尝试所有分类器。

步骤 5

现在创建模型,如图 5 所示:

Creating the model

lda_model=create_model (‘lda’)

线性判别分析分类器表现良好,如图 4 所示。因此,通过将 lda 传递给 create_model() 函数,我们可以拟合模型。

步骤 6

下一步是微调模型,如图 6 所示。

Tuning the model

tuned_lda=tune_model(lda_model)

超参数的调整可以提高模型的准确性。tune_model() 函数将线性判别分析模型的精度从 0.9818 提高到 0.9909,如图 7 所示。

Tuned model details

步骤 7

下一步是进行预测,如图 8 所示:

Predictions using the tuned model

predictions=predict_model(tuned_lda)

predict_model() 函数用于对测试数据中存在的样本进行预测。

步骤 8

现在绘制模型性能,如图 9 所示:

Evaluating and plotting the model performance — confusion matrix

evaluate_model(tuned_lda)

evaluate_model() 函数用于以最小的努力开发不同的性能指标。你可以尝试它们并查看输出。


via: https://www.opensourceforu.com/2022/05/pycaret-machine-learning-model-development-made-easy/

作者:S Ratan Kumar 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

如果你打算在今年探索 Rust,请下载我们的免费 Rust 速查表,以供快速参考基础知识。

 title=

Rust 是一门相对较新的编程语言,受到各个企业的 程序员的欢迎。尽管如此,它仍是一门建立在之前所有事物之上的语言。毕竟,Rust 不是一天做出来的,所以即便 Rust 中的一些概念看起来与你从 Python、Java、C++ 等编程语言学到的东西大不相同,但它们都是基于同一个基础,那就是你一直与之交互(无论你是否知道)的 CPU 和 NUMA( 非统一内存访问 Non Uniform Memory Access )架构,因此 Rust 中的一些新功能让人感觉有些熟悉。

现在,我的职业不是程序员。我没耐心但我又有点儿强迫症。当我需要完成某件事时,如果一门语言不能帮助我相对较快地获得想要的结果,那么我很少会受到鼓舞而使用它。Rust 试图平衡两个矛盾:现代计算机对安全和结构化代码的需求,和现代程序员对编码工作事半功倍的渴望。

安装 Rust

rust-lang.org 网站有丰富的的文档指导如何安装 Rust,但通常,它就像下载 sh.rustup.rs 脚本并运行它一样简单。

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs
$ less sh.rustup.sh
$ sh ./sh.rustup.rs

没有类

Rust 没有类,也不使用 class 关键字。Rust 确实有 struct 数据类型,但它的作用是充当数据集合的一种模板。因此,你可以使用 结构体 struct ,而不是创建一个类来表示虚拟对象:

struct Penguin {
  genus: String,
  species: String,
  extinct: bool,
  classified: u64,
}

你可以像使用类一样使用它。例如,当定义完 Penguin 结构,你就可以创建它的实例,并与该实例进行交互:

struct Penguin {
  genus: String,
  species: String,
  extinct: bool,
  classified: u64,
}

fn main() {
  let p = Penguin { genus: "Pygoscelis".to_owned(),
    species: "R adeliæ".to_owned(), 
    extinct: false, 
    classified: 1841 };

  println!("Species: {}", p.species);    
  println!("Genus: {}", p.genus);
  println!("Classified in {}", p.classified);
  if p.extinct == true {
    println!("Sadly this penguin has been made extinct.");
  }
}

impl 数据类型与 struct 数据类型结合使用,你可以实现一个包含函数的结构体,并且可以添加继承和其他与类相似的特性。

函数

Rust 中的函数很像其他语言中的函数。每个函数都代表一组严谨的任务,你可以在需要时调用它们。主函数名必须是 main

fn 关键字声明函数,后跟函数名称和函数接受的所有参数。

fn foo() {
  let n = 8;
  println!("Eight is written as {}", n);
}

通过参数,将信息从一个函数传递到另一个函数。例如,我已经创建了一个 Penguin 类(结构),并且我有一个 Penguin 的实例为 p,将目标函数的参数指定为 Penguin 类型,就可把 p 的属性从一个函数传递到另一个函数。

fn main() {
  let p = Penguin { genus: "Pygoscelis".to_owned(), 
    species: "R adeliæ".to_owned(), 
    extinct: false, classified: 1841 };
  printer(p);
}

fn printer(p: Penguin) {
  println!("Species: {}", p.species);    
  println!("Genus: {}", p.genus);
  println!("Classified in {}", p.classified);
  if p.extinct == true {
    println!("Sadly this penguin has been made extinct.");
  }
}

变量

Rust 默认创建的为 不可变 immutable 变量。这意味着你创建的变量以后无法更改。这段代码虽然看起来没问题,但无法编译:

fn main() {
  let n = 6;
  let n = 5;
}

但你可以使用关键字 mut 声明一个 可变 mutable 变量,因此下面这段代码可以编译成功:

fn main() {
  let mut n = 6;
  println!("Value is {}", n);
  n = 5;
  println!("Value is {}", n);
}

编译

Rust 编译器,至少就其报错信息而言,是可用的最好的编译器之一。当你在 Rust 中出错时,编译器会真诚地告诉你做错了什么。实际上,仅通过从编译器错误消息中学习,我就了解了 Rust 的许多细微差别(就我理解到的 Rust 的任何细微差别而言)。即便有时错误消息太过于模糊,而不知所以然,互联网搜索几乎总能得到解释。

启动 Rust 程序的最简单方法是使用 cargo,它是 Rust 的包管理和构建系统。

$ mkdir myproject
$ cd myproject
$ cargo init 

以上命令为项目创建了基本的基础架构,最值得注意的是 src 子目录中的 main.rs 文件。打开此文件,把我为本文生成的示例代码粘贴进去:

struct Penguin {
  genus: String,
  species: String,
  extinct: bool,
  classified: u64,
}

fn main() {
  let p = Penguin { genus: "Pygoscelis".to_owned(), species: "R adeliæ".to_owned(), extinct: false, classified: 1841 };
  printer(p);
  foo();
}

fn printer(p: Penguin) {
  println!("Species: {}", p.species);    
  println!("Genus: {}", p.genus);
  println!("Classified in {}", p.classified);
  if p.extinct == true {
    println!("Sadly this penguin has been made extinct.");
  }
}

fn foo() {
  let mut n = 6;
  println!("Value is {}", n);
  n = 8;
  println!("Eight is written as {}", n);
}

使用 cargo build 命令进行编译:

$ cargo build

执行 target 子目录下的二进制程序,或者直接运行 cargo run 命令来运行你的项目:

$ cargo run
Species: R adeliæ
Genus: Pygoscelis
Classified in 1841
Value is 6
Eight is written as 8

Crates

任何语言的大部分便利都来自于它的库或模块。在 Rust 中,进行分发和跟踪的库称为 “crate”(箱子)。crates.io 是一个很好的社区 crate 注册网站。

把一个 crate 添加到你的 Rust 项目,首先要在 Cargo.toml 文件中添加这个 crate。例如,要安装随机数函数,我使用名为 rand 的 crate,使用 * 作为通配符,以确保在编译时获得最新版本:

[package]
name = "myproject"
version = "0.1.0"
authors = ["Seth <[email protected]>"]
edition = "2022"

[dependencies]
rand = "*"

在 Rust 代码中使用它需要在最顶行使用 use 语句:

use rand::Rng;

以下是一些创建随机种子和随机范围的示例代码:

fn foo() {
  let mut rng = rand::thread_rng();
  let mut n = rng.gen_range(1..99);

  println!("Value is {}", n);
  n = rng.gen_range(1..99);
  println!("Value is {}", n);
}

你可以使用 cargo run 来运行它,它会检测代码是否被更改并触发一个新的构建。构建过程中下载名为 randcrete 和它依赖的所有 crate,编译代码,然后运行它:

$ cargo run
Updating crates.io index
Downloaded ppv-lite86 v0.2.16
Downloaded 1 crate (22.2 KB) in 1.40s
 Compiling libc v0.2.112
 Compiling cfg-if v1.0.0
 Compiling ppv-lite86 v0.2.16
 Compiling getrandom v0.2.3
 Compiling rand_core v0.6.3
 Compiling rand_chacha v0.3.1
 Compiling rand v0.8.4
 Compiling rustpenguin v0.1.0 (/home/sek/Demo/rustpenguin)
 Finished dev [unoptimized + debuginfo] target(s) in 13.97s
 Running `target/debug/rustpenguin`

Species: R adeliæ
Genus: Pygoscelis
Classified in 1841
Value is 70
Value is 35

Rust 速查表

Rust 是一门令人非常愉快的语言。集成了在线注册网站、有用的编译器和几乎直观的语法,它给人的适当的现代感。

但请不要误会,Rust 仍是一门复杂的语言,它具有严格的数据类型、强作用域变量和许多内置方法。Rust 值得一看,如果你要探索它,那么你应该下载我们的免费 Rust 速查表,以便快速了解基础知识。越早开始,就越早了解 Rust。当然,你应该经常练习以避免生疏。

Rust 速查表

via: https://opensource.com/article/22/1/rust-cheat-sheet

作者:Seth Kenlon 选题:lujun9972 译者:hanszhao80 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

通过理解和使用 JVM 以及 JVM 参数,开发人员和最终用户都可以诊断故障并且提高 Java 应用程序的性能。

当你在编写源代码时,你是在编写人类可以阅读的代码。在将代码编译成机器语言之前,计算机无法执行它。机器语言是一个通用术语,指的是特定机器所需的任意数量的语言。通常,如果你在 Linux 上编译代码,它只能 Linux 上运行;如果你在 Windows 上编译代码,它就只在 Windows 上运行。但是,Java 是不同的,它并不以真实的机器为目标,而是面向 Java 虚拟机 Java Virtual Machine (JVM)。因此,它可以在任何机器上运行。

Java 源代码被编译成 字节码 bytecode ,然后由安装在计算机上的 JVM 运行。JVM 是一个执行引擎,但我们通常不会直接与它交互。它在后台静默运行,替我们处理 Java 字节码。大多数人不需要考虑,甚至也不需要知道 JVM。但是,了解它的工作原理是对我们来说是非常有用的,因为这会有助于我们调试和优化 Java 代码。例如:

  • 在生产环境中,你发现已经部署的应用程序可能需要提升性能。
  • 如果你写的应用程序出错了,开发人员和最终用户都可以选择对问题进行调试。
  • 如果你想了解关于 JDK(即 Java 开发工具包 Java Development Kit ,用于开发/运行 Java 应用程序)的详细信息,你可以通过查询 JVM 来获取。

本文介绍了一些基础的 JVM 参数,希望在这些场景中可以提供帮助。

JVM 参数

(图源:Jayashree Huttanagoudar,CC BY-SA 4.0)

JVM、JDK 和 JRE 有什么不同?

Java 有许多 J 开头的缩略词,包括 JVM、JDK 和 JRE。

  • Java 开发工具包 Java Development Kit (JDK)可供需要在代码中使用开发库的程序员使用。
  • Java 运行时环境 Java Runtime Environment (JRE)可供想运行 Java 应用程序的人使用。
  • Java 虚拟机 Java Virtual Machine (JVM)是运行 Java 字节码的组件。

JDK 同时包含 JRE 和 JVM,但有些 Java 发行版提供了包含 JRE(包括 JVM)的替代下载。

JDK

(图源:Jayashree Huttanagoudar,CC BY-SA 4.0)

Java 是开源的,因此,许多不同的公司都会构建和发行他们自己的 JDK 发行版。你可以在系统上安装多个 JDK,这会对你参与或者运行不同的 Java 项目时很有帮助,因为其中一些项目可能使用旧版本的 JDK。

你可以使用 alternatives 命令,来查看 Linux 系统上的 JDK 列表:

$ alternatives --config java
There are 2 programs that provide java.
Selection Command
-----------------------------------------------
*+ 1 java-11-openjdk.x86_64 (/usr/lib/jvm/java-11-openjdk-11.0.13.0.8-2.fc35.x86_64/bin/java)
2 java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.312.b07-2.fc35.x86_64/jre/bin/java)

Enter to keep the current selection[+], or type selection number:

如果想要在可用的 JDK 之间进行切换,请再次执行该命令:

$ sudo alternatives --config java

或者可以使用 SDKMan,它可以下载、更新和管理系统中的所有 JDK。

什么是 JVM 调优?

JVM 调优指的是,通过调整 JVM 参数,来提高 Java 应用程序性能的过程,它还有助于诊断应用程序的故障。

通常情况下,在调试之前需要考虑以下几点:

  • 成本:有时改进运行代码的硬件可以提高应用程序的性能。这可能看起来像是在“作弊”,但请考虑你愿意花多少时间调整 JVM 参数。有时应用程序需要更多的内存来执行所需的功能,而这点是任何软件技术都无法改变的。
  • 期望结果:长期来看,稳定性比性能更重要。如果你的调优对稳定性产生了影响,那么谨慎地选择你的调优参数可能会更好。
  • 底层问题:有时,问题可能是主机操作系统的底层问题。那么,在调整 JVM 之前,请确保 JVM 平台按预期工作。
  • 内存泄漏:如果你在使用垃圾回收(GC)调优参数,那么,应用程序代码中很可能会存在需要修复的内存泄漏。

参数类型

JVM 参数可以分为以下三类:标准参数、非标准参数和高级选项。

标准参数

所有的 JVM 实现都支持标准参数,在终端执行 java 命令来查看标准参数列表:

$ java
Usage: java [options] <mainclass> [args...]
        (to execute a class)
   or  java [options] -jar <jarfile> [args...]
        (to execute a jar file)

 where options include:

        -cp <class search path of directories and zip/jar files>
        -classpath <class search path of directories and zip/jar files>
        --class-path <class search path of directories and zip/jar files>
                A : separated list of directories, JAR archives,
                and ZIP archives to search for class files.
        --enable-preview
                allow classes to depend on preview features of this release

To specify an argument for a long option, you can use --<name>=<value> or
--<name> <value>.

这些是所有 JVM 都会包含的标准参数,你可以像使用任何 命令行选项 一样安全地使用它们。例如,要验证配置的命令选项,创建 VM 并加载主类而不执行主类,请使用:

$ java --dry-run <classfile>

非标准参数

非标准选项以 -X 开头。这些是通用的,并且特定于 JVM 的特定实现。要列出这些参数,请输入:

$ java -X
-Xbatch disable background compilation
-Xbootclasspath/a:<directories and zip/jar files separated by :>
append to end of bootstrap class path
-Xinternalversion
displays more detailed JVM version information than the
-version option
-Xloggc:<file> log GC status to a file with time stamps
[...]

在这些参数可能会不经通知就发生变化。而且,并非所有 JVM 实现都支持这些参数。

微软构建的 JVM 可能与 RedHat 构建的 JVM 有不同的参数,诸如此类。

要获取详细的 JVM 版本信息,请使用如下命令:

$ java -Xinternalversion --version
OpenJDK 64-Bit Server VM (11.0.13+8) for linux-amd64 JRE (11.0.13+8), built on Nov 8 2021 00:00:00 by "mockbuild" with gcc 11.2.1 20210728 (Red Hat 11.2.1-1)

要获取这些属性设置,请使用:

$ java -XshowSettings:properties --version

高级选项

这些参数不是随意使用的,而是用于调整 Hotspot VM 的特定区域。这些参数可能会发生变化,并且不能保证得到所有 JVM 实现的支持。

这些参数以 -XX 开头。如需列出参数列表,使用如下命令:

$ java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version

例如,需要跟踪类的加载,那么使用下面的命令:

$ java -XX:+TraceClassLoading Hello

Hello.java 中:

public class Hello {
  public static void main(String[] args) {
    System.out.println("Inside Hello World!");
  }
}

另一个可能会面临的问题是 OOM( 内存超出 Out Of Memory )错误,它发生的时候可能没有太多的调试信息。为了解决这个问题,使用调试参数 -XX:+HeapDumpOnOutOfMemoryError,它可以创建一个带有调试信息的 .hprof 文件。

// TestClass.java
import java.util.ArrayList;
import java.util.List;

public class TestClass {
  public static void main(String[] args) {
    List<Object> list = new ArrayList<Object>();
    for (int i = 0; i < 1000; i++) {
      list.add(new char[1000000]);
    }
  }
}
$ Javac TestClass.java
$ java -XX:+HeapDumpOnOutOfMemoryError -Xms10m -Xmx1g TestClass
java.lang.OutOfMemoryError: java heap space
Dumping heap to java_pid444496.hprof ...
Heap dump file created [1018925828 bytes in 1.442 secs]
Exception in thread "main" java.lang.OutOfMemoryError: java heap space
at TestClass.main(TestClass.Java:8)

有一些工具 可以查看这个 .hprof 文件以了解问题所在。

总结

通过了解和使用 JVM 以及 JVM 参数,开发人员和终端用户都可以诊断故障并提高 Java 应用程序的性能。下次使用 Java 时,请花点时间看看有哪些参数可以用吧!

(题图由 Seksak KerdkannoPixabay 上发布 )


via: https://opensource.com/article/22/4/jvm-parameters-java-developers

作者:Jayashree Huttanagoudar 选题:lkxed 译者:Veryzzj 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在网络钓鱼攻击中,用户会收到一封带有误导性链接的邮件或信息,攻击者可以利用它来收集重要数据,比如你的银行卡密码。本文将会给出一个简短的教程,旨在介绍如何检测这种网络钓鱼的企图。

通过网络钓鱼攻击,攻击者能够获得一些重要凭证,这些凭证可以用来进入你的银行或其他金融账户。攻击者发送的 URL 看起来与我们日常使用的原始应用程序完全相同。这也是人们经常相信它,并在其中输入个人信息的原因。钓鱼网址可以打开一个网页,它看起来与你的银行的原始登录页面相似。最近,这样的网络钓鱼攻击正变得相当普遍,所以,检测钓鱼链接变得非常重要。因此,我将介绍如何在 Python 中使用机器学习来检查一个链接是误导性的还是真实的,因为它可以帮助我们看到网页代码及其输出。注意,本文将使用 Jupyter Notebook。当然,你也可以使用 Google Colab 或 Amazon Sagemaker,如果你对这些更熟悉的话。

下载数据集

第一步,我们需要用于训练数据集。你可以从下面的链接中下载数据集。

训练机器进行预测

当数据集下载完成,我们需要使用以下几行代码来导入所需的库:

import pandas as pd
from sklearn.ensemble import RandomForestClassifier

如果你没有这些库,你可以使用 pip 工具来安装这些库,如下图所示:

使用 pip 工具安装依赖库

当依赖安装完成,你就可以导入数据集,并将其转换为 pandas 数据框架,使用以下几行代码进一步处理:

legitimate_urls = pd.read_csv(“/home/jishnusaurav/jupyter/Phishing-Website-Detection/datasets/legitimate-urls.csv”)
phishing_urls = pd.read_csv(“/home/jishnusaurav/jupyter/Phishing-Website-Detection/datasets/phishing-urls.csv”)

在成功导入后,我们需要把这两个数据集合并,以便形成一个数据集。合并后的数据集的前几行如下图所示:

合并后的数据集的前几行

然后去掉那些我们不需要的列,如路径(path)、协议(protocol)等,以达到预测的目的:

urls = urls.drop(urls.columns[[0,3,5]],axis=1)

在这之后,我们需要使用以下代码将数据集分成测试和训练两部分:

data_train, data_test, labels_train, labels_test = train_test_split(urls_without_labels, labels, test_size=0.30, random_state=110)

接着,我们使用 sklearn 的随机森林分类器建立一个模型,然后使用 fit 函数来训练这个模型。

random_forest_classifier = RandomForestClassifier()
random_forest_classifier.fit(data_train,labels_train)

完成这些后,我们就可以使用 predict 函数来最终预测哪些链接是钓鱼链接。下面这行可用于预测:

prediction_label = random_forest_classifier.predict(test_data)

就是这样啦!你已经建立了一个机器学习模型,它可以预测一个链接是否是钓鱼链接。试一下吧,我相信你会满意的!


via: https://www.opensourceforu.com/2022/04/detect-a-phishing-url-using-machine-learning-in-python/

作者:Jishnu Saurav Mittapalli 选题:lkxed 译者:lkxed 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出